MPlayer开发

一、介绍
    不论是音频数据还是视频数据,我都为MPlayer项目开发过一些开源的解码器。因此我个人认为我有资格写一篇文档来介绍如何开发新的编解码器。
    学习如何添加一个新的编解码器的最好方法通常是学习大量的已有代码。本文档仅仅是对代码的一个补充,给出一些技巧、关键点和一般的路线图。
    术语介绍:“Codec"表示编码器/解码器(如果你愿意,也可以称为压缩器/解压缩器),它表示一个模块既可以对数据进行编码,也可以进行解码。然而本文档主要是针对解码器,而术语“decoder”和“codec”通常也被一起使用。

二、必要的资源
    当你决定要为MPlayer实现一个新的解码器时,那么下面这些应该是你需要的:
(1)实现编解码器的知识
    你需要知道MPlayer传给你的数据格式,知道如何把其中的数据结构拆开,在重组这些原始的媒体数据时,需要知道对这些数据的算法操作。
(2)媒体样本
    MPlayer在解码时需要确切地知道如何解析存储在媒体文件中经编码后的数据格式(包括AVI,ASF,MOV,RM,VIVO等等)。如果MPlayer无法识别媒体文件中的编码数据,那么你就必须把这种格式转换为能识别的格式,或者为MPlayer写你自己的文件解复用器来处理这些数据。如何写解复用器已经超出了本文档的论述范围,此处不做论述。
    尽力获得支持所有可能模式的解码器的媒体样本。如果一个音频的编解码器同时支持单声道和立体声,那么就要找到相应的媒体样本来测试。如果一个视频编解码器能够同时工作在7种不同的比特率,那么你也要想尽办法去获得相应7种比特率编码的媒体样本。
(3)最新的CVS快照
    为最新的MPlayer开发版本来开发编解码器同样也是很重要的,因此要经常用CVS更新你的版本。
(4)普通的编程知识,能在Linux环境下开发
    这通常是不用说的,但有时候你却不得不说。

三、开发流程
(1)建立基本的开发环境
    首先,修改你的本地配置文件codecs.conf,它可能是系统共享的或在你主目录下。为你的编解码器添加一个新的条目,如果是开源的编解码器,那么最好把它放在其他开源的编解码器一起。当你确信把条目添加正确后,一定要把它添加到你的工作目录的etc/codecs.conf中。想要了解这个配置文件的详细信息,可以查看codecs.conf.txt。创建一个新的包含相关信息,格式,输出格式,特定驱动名称的音频编解码或视频编解码块,并记住驱动的名称。
    创建一个新的源文件,它应该包含解码的主函数以便MPlayer调用来进行解码数据。最终你可能会有多个文件组成你的解码器,举一个简单的例子如下:
对于一个音频解码器,比如ad_sample.c。针对视频解码器,可以命名为vd_*.c。
    接下来,需要修改Makefile文件使得新的编解码器被编译进去。当然,你还需要把解码器加入到ad.c(对音频来说)或vd.c(对视频来说)的数组中。
    编译整个工程,看看到目前为止是否有错误。
    为了把你的解码函数放在首要位置,你需要确保你的编码数据。这听起来像是一个微小的练习,但却可能发生很多错误。在你解码函数的开始,加入下面的代码:
    int i;
    for (i = 0; i < 16; i++)
        printf ("%02X ", input[i]);
    printf ("/n");
    当你编译并运行MPlayer时,你的解码函数将会打印它所接收到的每个数据块的前16个字节。用16进制编辑器打开媒体样本,看看你屏幕上的输出和打开文件所看到的,如果解码器打印的与文件中的一致,那么说明你已经准备好进入第二步了,否则你就要找出为什么没有得到正确的数据,是因为解码器没有被触发吗?为什么?
(2)开发解码器
    记住首先要让它能工作,其次才是工作的快。
    解码器支持什么输出格式?任何都可以。通常YUV输出要比RGB输出受欢迎。如果一个编码器采用YUV数据作为它的源数据,那么就需要能解码一个YUV数据的帧。如果编码器想很多老的视频编码器一样用RGB数据作为输入,那么支持YUV输出就没有意义了,尽可能的输出RGB格式就可以了。
    最受欢迎的视频数据输出格式是YV12,因为MPlayer支持大量的硬件设备来对这些数据直接显示、缩放和过滤。MPlayer同样也有很多优化的转换函数能把YV12数据转换为其他数据输出格式。
    如果你确实采用RGB作为输出,你必须意识到MPlayer事实上打包RGB为BGR,如果你解码成BGR24数据缓存,那么输出如下:
    B G R B G R B G R B ...
    如果你解码成BGR32,那么在每个BGR后面需要一个额外的字节:
    B G R - B G R - B G ...
    很好地利用检查方法。在解码器的开始包含头文件mp_msg.h,你可以使用mp_msg()函数作为你的printf()语句。一旦你的解码器发现奇怪的数据或情况,打印如下:
    mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Odd data encountered: %d/n", data);
显然,为了你好,你应该使得消息更加清晰。MSGL_WARN对这种类型的信息来说是一个好的消息级别。mp_msg.h中定义了所有的错误级别,你甚至可以用MSGL_FATAL来使得MPlayer完全退出,但这不是解码数据需要的级别。
    什么情况下应该触发一个警告呢?任何超出普通的情况。许多压缩的视频数据包含的头里有宽、高和大小这些数据,把这些域作为参数传给解码函数,这些数据应该是匹配的,否则应该给出一个警告并决定应该使用哪个数据。如果头部信息里应该有一个Magic Number,或是从头部数据计算出来的,但却不正确,则应该给出警告。
    无论检查边界索引有多枯燥,你都必须确保没有超出理论上的内存范围,访问超出范围的内存会导致段错误,永远不要相信传递给你的所有数据都是正确的。一旦索引超出了范围,就需要给出警告并退出解码过程(而不是整个应用程序)。
    写出所有可能产生警告的情况看似无聊的,但如果不写的话,万一在解码过程中出现错误,你却不知道是为什么以及在哪里出了错误。
(3)调试和测试解码器
    如果你超级幸运,解码器第一次运行就成功了;或是你很幸运,通过修改了几个程序错误以后,你的解码器也能工作了。现实来说,你需要查看很多次,修改很多明显和不明显的程序错误,还需要通过调试来解决一个很小的功能。
    提示:请求所有的警告信息。例如gcc的-Wall选项。开发时使用调试模式是很有用的,为了在调试模式下编译你的MPlayer,使用--enable-debug选项。注意所有的警告并消除所有警告。
(4)把解码器贡献到代码库
    用"diff -u"来创建一个补丁,然后给MPlayer开发组发邮件获得许可,你需要diff下列文件:
    - Makefile
    - etc/codecs.conf
    - ad.c or vd.c
    当然,你应该包含你新创建的文件:vd_<name>.c 或 ad_<name>.c。如果你贡献够多的话,MPlayer开发组或许会授予你修改CVS的权利。
(5)等待BUG报告并跟进

    当你发布你的编解码器后,你也许认为你已经完成了,但前提是你足够幸运。但往往却事与愿违,所以你需要查看BUG报告并跟进修改BUG。


MPlayer编解码开发指导

一、介绍
    不论是音频数据还是视频数据,我都为MPlayer项目开发过一些开源的解码器。因此我个人认为我有资格写一篇文档来介绍如何开发新的编解码器。
    学习如何添加一个新的编解码器的最好方法通常是学习大量的已有代码。本文档仅仅是对代码的一个补充,给出一些技巧、关键点和一般的路线图。
    术语介绍:“Codec"表示编码器/解码器(如果你愿意,也可以称为压缩器/解压缩器),它表示一个模块既可以对数据进行编码,也可以进行解码。然而本文档主要是针对解码器,而术语“decoder”和“codec”通常也被一起使用。

二、必要的资源
    当你决定要为MPlayer实现一个新的解码器时,那么下面这些应该是你需要的:
(1)实现编解码器的知识
    你需要知道MPlayer传给你的数据格式,知道如何把其中的数据结构拆开,在重组这些原始的媒体数据时,需要知道对这些数据的算法操作。
(2)媒体样本
    MPlayer在解码时需要确切地知道如何解析存储在媒体文件中经编码后的数据格式(包括AVI,ASF,MOV,RM,VIVO等等)。如果MPlayer无法识别媒体文件中的编码数据,那么你就必须把这种格式转换为能识别的格式,或者为MPlayer写你自己的文件解复用器来处理这些数据。如何写解复用器已经超出了本文档的论述范围,此处不做论述。
    尽力获得支持所有可能模式的解码器的媒体样本。如果一个音频的编解码器同时支持单声道和立体声,那么就要找到相应的媒体样本来测试。如果一个视频编解码器能够同时工作在7种不同的比特率,那么你也要想尽办法去获得相应7种比特率编码的媒体样本。
(3)最新的CVS快照
    为最新的MPlayer开发版本来开发编解码器同样也是很重要的,因此要经常用CVS更新你的版本。
(4)普通的编程知识,能在Linux环境下开发
    这通常是不用说的,但有时候你却不得不说。

三、开发流程
(1)建立基本的开发环境
    首先,修改你的本地配置文件codecs.conf,它可能是系统共享的或在你主目录下。为你的编解码器添加一个新的条目,如果是开源的编解码器,那么最好把它放在其他开源的编解码器一起。当你确信把条目添加正确后,一定要把它添加到你的工作目录的etc/codecs.conf中。想要了解这个配置文件的详细信息,可以查看codecs.conf.txt。创建一个新的包含相关信息,格式,输出格式,特定驱动名称的音频编解码或视频编解码块,并记住驱动的名称。
    创建一个新的源文件,它应该包含解码的主函数以便MPlayer调用来进行解码数据。最终你可能会有多个文件组成你的解码器,举一个简单的例子如下:
对于一个音频解码器,比如ad_sample.c。针对视频解码器,可以命名为vd_*.c。
    接下来,需要修改Makefile文件使得新的编解码器被编译进去。当然,你还需要把解码器加入到ad.c(对音频来说)或vd.c(对视频来说)的数组中。
    编译整个工程,看看到目前为止是否有错误。
    为了把你的解码函数放在首要位置,你需要确保你的编码数据。这听起来像是一个微小的练习,但却可能发生很多错误。在你解码函数的开始,加入下面的代码:
    int i;
    for (i = 0; i < 16; i++)
        printf ("%02X ", input[i]);
    printf ("/n");
    当你编译并运行MPlayer时,你的解码函数将会打印它所接收到的每个数据块的前16个字节。用16进制编辑器打开媒体样本,看看你屏幕上的输出和打开文件所看到的,如果解码器打印的与文件中的一致,那么说明你已经准备好进入第二步了,否则你就要找出为什么没有得到正确的数据,是因为解码器没有被触发吗?为什么?
(2)开发解码器
    记住首先要让它能工作,其次才是工作的快。
    解码器支持什么输出格式?任何都可以。通常YUV输出要比RGB输出受欢迎。如果一个编码器采用YUV数据作为它的源数据,那么就需要能解码一个YUV数据的帧。如果编码器想很多老的视频编码器一样用RGB数据作为输入,那么支持YUV输出就没有意义了,尽可能的输出RGB格式就可以了。
    最受欢迎的视频数据输出格式是YV12,因为MPlayer支持大量的硬件设备来对这些数据直接显示、缩放和过滤。MPlayer同样也有很多优化的转换函数能把YV12数据转换为其他数据输出格式。
    如果你确实采用RGB作为输出,你必须意识到MPlayer事实上打包RGB为BGR,如果你解码成BGR24数据缓存,那么输出如下:
    B G R B G R B G R B ...
    如果你解码成BGR32,那么在每个BGR后面需要一个额外的字节:
    B G R - B G R - B G ...
    很好地利用检查方法。在解码器的开始包含头文件mp_msg.h,你可以使用mp_msg()函数作为你的printf()语句。一旦你的解码器发现奇怪的数据或情况,打印如下:
    mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Odd data encountered: %d/n", data);
显然,为了你好,你应该使得消息更加清晰。MSGL_WARN对这种类型的信息来说是一个好的消息级别。mp_msg.h中定义了所有的错误级别,你甚至可以用MSGL_FATAL来使得MPlayer完全退出,但这不是解码数据需要的级别。
    什么情况下应该触发一个警告呢?任何超出普通的情况。许多压缩的视频数据包含的头里有宽、高和大小这些数据,把这些域作为参数传给解码函数,这些数据应该是匹配的,否则应该给出一个警告并决定应该使用哪个数据。如果头部信息里应该有一个Magic Number,或是从头部数据计算出来的,但却不正确,则应该给出警告。
    无论检查边界索引有多枯燥,你都必须确保没有超出理论上的内存范围,访问超出范围的内存会导致段错误,永远不要相信传递给你的所有数据都是正确的。一旦索引超出了范围,就需要给出警告并退出解码过程(而不是整个应用程序)。
    写出所有可能产生警告的情况看似无聊的,但如果不写的话,万一在解码过程中出现错误,你却不知道是为什么以及在哪里出了错误。
(3)调试和测试解码器
    如果你超级幸运,解码器第一次运行就成功了;或是你很幸运,通过修改了几个程序错误以后,你的解码器也能工作了。现实来说,你需要查看很多次,修改很多明显和不明显的程序错误,还需要通过调试来解决一个很小的功能。
    提示:请求所有的警告信息。例如gcc的-Wall选项。开发时使用调试模式是很有用的,为了在调试模式下编译你的MPlayer,使用--enable-debug选项。注意所有的警告并消除所有警告。
(4)把解码器贡献到代码库
    用"diff -u"来创建一个补丁,然后给MPlayer开发组发邮件获得许可,你需要diff下列文件:
    - Makefile
    - etc/codecs.conf
    - ad.c or vd.c
    当然,你应该包含你新创建的文件:vd_<name>.c 或 ad_<name>.c。如果你贡献够多的话,MPlayer开发组或许会授予你修改CVS的权利。
(5)等待BUG报告并跟进
    当你发布你的编解码器后,你也许认为你已经完成了,但前提是你足够幸运。但往往却事与愿违,所以你需要查看BUG报告并跟进修改BUG。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/455052.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

可编程led灯带原理_SCPSD-250-04-27派克真空压力传感器故障和工作原理

SCPSD-250-04-27派克PARKER真空压力传感器故障和工作原理PARKER压力开关现货 PARKER压力传感器特价 派克真空压力传感器 PARKER数字压力开关2020年还剩最后2天了&#xff0c;这一年大家都过得不太容易&#xff0c;尤其是我自己这是30年以来过得最艰难的一年&#xff0c;经…

总结面试时没有回答上的内存对齐问题

前两天面试某公司时&#xff0c;没有回答上的一个问题&#xff0c;总结如下&#xff0c;以供参考。 问&#xff1a;下面这个结构类型的实例变量占用多少内存&#xff1a; struct struct1 { int i; short j; char c; }; 我反问&#xff1a;是啥语言啥机器啥编译环境…

Kibana入门安装与介绍

Kibana入门 Kibana 是一款开源的数据分析和可视化平台&#xff0c;它是 Elastic Stack 成员之一&#xff0c;设计用于和 Elasticsearch 协作。您可以使用 Kibana 对 Elasticsearch 索引中的数据进行搜索、查看、交互操作。您可以很方便的利用图表、表格及地图对数据进行多元化…

友善串口工具接收数据随机换行_使用Python3+PyQT5+Pyserial 实现简单的串口工具方法...

练手项目&#xff0c;先上图先实现一个简单的串口工具&#xff0c;为之后的上位机做准备代码如下&#xff1a;pyserial_demo.pyimport sys import serial import serial.tools.list_ports from PyQt5 import QtWidgets from PyQt5.QtWidgets import QMessageBox from PyQt5.QtC…

Vue渲染函数

前面的话 Vue 推荐在绝大多数情况下使用 template 来创建HTML。然而在一些场景中&#xff0c;真的需要 JavaScript 的完全编程的能力&#xff0c;这就是 render 函数&#xff0c;它比 template 更接近编译器。本文将详细介绍Vue渲染函数 引入 下面是一个例子&#xff0c;如果要…

数据绑定原理

一、数据单向绑定原理指先把模板写好&#xff0c;然后把模板和数据(数据可能来自后台)整合到一起形成HTML代码&#xff0c;最后把这段HTML代码插入到文档流里。缺点&#xff1a;一旦HTML代码生成就没有办法改变&#xff0c;如果有新数据重新传入&#xff0c;就必须重新把模板和…

视频解码优化

以下通过剖析一些经验来了解视频解码优化 1. 在嵌入式系统中实现MPEG4的视频解码 有两种方法可行 (1)采用ffmpeg(mplayer 的核心就是采用ffmpeg)&#xff0c;然后对ffmpeg mp4解码优化 1).对IDCT汇编化,并优化VLD的实现 ->inline&汇编化 2).根据ARM9 cache&cache…

Logstash入门简介

Logstash入门简介 介绍 Logstash是一个开源的服务器端数据处理管道&#xff0c;能够同时从多个来源采集数据&#xff0c;转换数据&#xff0c;然后将数据发送到最喜欢的存储库中&#xff08;我们的存储库当然是ElasticSearch&#xff09; 我们回到我们ElasticStack的架构图&a…

Django templates 和 urls 拆分

如果在Django项目 下面新建了blog和polls两个APP应用&#xff0c;在每个APP下面都各自新建自己的url和templates&#xff0c;那么我们需要如何进行项目配置呢&#xff1f; INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, dja…

springboot怎么杀进程_线上服务平均响应时间太长,怎么排查?

线上服务平均响应时间太长&#xff0c;怎么排查&#xff1f;https://xie.infoq.cn/article/914b5c56000a3880016abd8d6前言&#xff1a;最近线上环境某个接口服务响应时间偏长&#xff0c;导致用户体验超差&#xff0c;那平时该怎么快速的排查这类问题呢&#xff1f;①、为代码…

Redis学习第五课:Redis Set类型及操作

Set是集合&#xff0c;它是string类型的无序集合。set是通过hash table实现的&#xff0c;添加、删除和查找的复杂度都是O(1)。 对集合我们可以取并集、交集、差集。通过这些操作我们可以实现SNS中的好友推荐和blog的tag功能。 Set集合操作&#xff1a; sadd:向名称为Key的set中…

MPEG音视频编解码之MP3编解码概述

2 MP3编解码原理 2.1 MP3音频压缩标准概述 MP3全称是动态影像专家压缩标准音频层面3&#xff08;Moving Picture Experts Group Audio Layer III&#xff09;。是当今较流行的一种数字音频编码和有损压缩格式&#xff0c;它设计用来大幅度地降低音频数据量&#xff0c;而对于…

Python实现GitBook工具

写在前面 本工具是通过Python脚本实现 GitBook 自动 生成 执行 编译 发布的功能 你可以在这里下载exe 使用 1. exe下载,并移动位置 将exe文件放在你的gitbook文件夹中,或者放在空文件夹中 2. file.md 创建 名为file.md的文件,在你要写book的目录下 注意: 这里file.md文件名…

shell脚本中用到的条件和循环语句

本博文介绍一下shell脚本中常用的条件和循环语句&#xff1a;条件语句&#xff1a;循环语句&#xff1a;示例&#xff1a;if语句&#xff1a;eg1.eg2.2.case语句&#xff1a;简单的case语句&#xff1a;配合循环的case语句&#xff1a;3.for语句&#xff1a;简单的for语句&…

BZOJ 2243 染色(树链剖分好题)

2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 7971 Solved: 2990[Submit][Status][Discuss] Description 给定一棵有n个节点的无根树和m个操作&#xff0c;操作有2类&#xff1a; 1、将节点a到节点b路径上所有点都染成颜色c&#xff1b; 2、询问…

processing动态代码大全_做一张动态海报需要多少步?

人们习惯性地把程序员跟设计师分成两种不同性质的人&#xff0c;好像程序员就不会有美感&#xff0c;设计师逻辑思维就一定会很弱&#xff0c;但最近几年我们发现越来越多的程序员学设计&#xff0c;设计师学编程的跨界故事。新媒体艺术家&#xff0c;邱伟豪也是其中一员&#…

【ffmpeg for wince】音视频编解码多平台移植(for window/wince)

from: http://www.cnblogs.com/windwithlife/archive/2009/05/31/1492728.html 终于完成了了第二个Client side原型&#xff08;for Wince)&#xff0c;其中花掉我最多时间的就是ffmpeg的对WINCE的移植。其中有大半时间是由于网上的一些不完整及不正确信息所误导&#xff0c;…

python实现猴子爬山算法

猴子爬山一只顽猴在一座有N级台阶的小山上爬山跳跃。上山时需从山脚至山顶往上跳N级台阶&#xff0c;一步可跳1级&#xff0c;或跳3级&#xff0c;求上山有多少种不同的跳法&#xff1f; &#xff08;N<50&#xff09; 问题分析: 每一次都可以选择1,2,3有3种跳法 方法1 直…

指针版 单链表复习

#include <bits/stdc.h> #define P pair<int,int> using namespace std;typedef long long LL;typedef struct LNode{int data;struct LNode *nxt; }LNode,*LinkList;bool Linklist_init(LinkList &root){root new LNode; ///分配头结点&#xff0c;指针域为空…

手写springboot_Spring Boot 入门教程 | 图文讲解

目录一、Spring Boot 是什么二、为什么要使用 Spring Boot三、快速入门3.1 创建 Spring Boot 项目3.2 项目结构3.3 引入 Web 依赖3.4 编写第一个接口3.5 启动程序&#xff0c;验证效果四、总结五、GitHub 示例代码一、Spring Boot 是什么以下截图自 Spring Boot 官方文档&#…