FFmpeg SDK开发模型之三:muxer

简介

使用FFmpeg SDK实现的H.264码流合成MPEG2-TS文件

一、源代码

int main(int argc, char* argv[])

{

const char* input = NULL;

const char* output= NULL;

/* Obtain input params */

if (argc <= 1) {

printf("Usage:\n");

printf("%s <input_file.264> <output_file.ts>\n", argv[0]);

return 0;

}

input = argv[1];

output= argv[2];

AVInputFormat* ifmt  = NULL;

AVOutputFormat* ofmt = NULL;

AVFormatContext* ic  = NULL;

AVFormatContext* oc  = NULL;

AVStream* video_st   = NULL;

AVStream* audio_st   = NULL;

AVCodec* codec = NULL;

AVDictionary* pAVDictionary = NULL;

avcodec_init();

avcodec_register_all();

av_register_all();

ifmt = av_find_input_format("avc");

ic = avformat_alloc_context();

if (!ic)

{

printf("Call avformat_alloc_context failed!\n");

return 0;

}

char szError[256] = {0};

int nRet = avformat_open_input(&ic, input, ifmt, &pAVDictionary);

if (nRet != 0)

{

av_strerror(nRet, szError, 256);

printf(szError);

printf("\n");

printf("Call avformat_open_input function failed!\n");

return 0;

}

if (avformat_find_stream_info(ic, NULL) < 0)

{

printf("Call av_find_stream_info function failed!\n");

return 0;

}

ofmt = av_guess_format("mpegts", NULL, NULL);

if (!ofmt)

{

printf("Call av_guess_format function failed!\n");

return 0;

}

oc = avformat_alloc_context();

if (!oc)

{

printf("Call av_guess_format function failed!\n");

return 0;

}

oc->oformat = ofmt;

int video_index = -1, audio_index = -1;

unsigned int i;

for (i = 0; i < ic->nb_streams && (video_index < 0 || audio_index < 0); i++)

{

switch (ic->streams[i]->codec->codec_type)

{

case AVMEDIA_TYPE_VIDEO:

video_index = i;

ic->streams[i]->discard = AVDISCARD_NONE;

video_st = add_output_stream(oc, ic->streams[i]);

break;

case AVMEDIA_TYPE_AUDIO:

audio_index = i;

ic->streams[i]->discard = AVDISCARD_NONE;

audio_st = add_output_stream(oc, ic->streams[i]);

break;

default:

ic->streams[i]->discard = AVDISCARD_ALL;

break;

}

}

codec = avcodec_find_decoder(video_st->codec->codec_id);

if (codec == NULL)

{

printf("Call avcodec_find_decoder function failed!\n");

return 0;

}

if (avcodec_open(video_st->codec, codec) < 0)

{

printf("Call avcodec_open function failed !\n");

return 0;

}

if (avio_open(&oc->pb, output, AVIO_FLAG_WRITE) < 0)

{

return 0;

}

if (avformat_write_header(oc, &pAVDictionary))

{

printf("Call avformat_write_header function failed.\n");

return 0;

}

uint8_t *dummy = NULL;

int dummy_size = 0;

AVBitStreamFilterContext* bsfc =  av_bitstream_filter_init("h264_mp4toannexb");

if(bsfc == NULL)

{

return -1;

}

int decode_done = 0;

do

{

double segment_time = 0;

AVPacket packet;

decode_done = av_read_frame(ic, &packet);

if (decode_done < 0)

break;

if (av_dup_packet(&packet) < 0)

{

printf("Call av_dup_packet function failed\n");

av_free_packet(&packet);

break;

}

static int nCount = 0;

if (nCount++ < 20)

{

printf("The packet.stream_index is %ld\n", packet.stream_index);

}

if (packet.stream_index == video_index)

{

if (packet.pts != (u_int)AV_NOPTS_VALUE)

{

packet.pts      = av_rescale_q(packet.pts,ic->streams[video_index]->time_base,video_st->time_base);

}

if (packet.dts != (u_int)AV_NOPTS_VALUE)

{

packet.dts      = av_rescale_q(packet.dts,ic->streams[video_index]->time_base,video_st->time_base);

}

}

nRet = av_interleaved_write_frame(oc, &packet);

if (nRet < 0)

{

printf("Call av_interleaved_write_frame function failed\n");

}

else if (nRet > 0)

{

printf("End of stream requested\n");

av_free_packet(&packet);

break;

}

av_free_packet(&packet);

}while(!decode_done);

av_write_trailer(oc);

av_bitstream_filter_close(bsfc);

avcodec_close(video_st->codec);

unsigned int k;

for(k = 0; k < oc->nb_streams; k++)

{

av_freep(&oc->streams[k]->codec);

av_freep(&oc->streams[k]);

}

av_free(ic);

av_free(oc);

getchar();

return 0;

}

二、源码分析

01  avcodec_init();         初始化libavcodec

02  avcodec_register_all(); 注册所有的codec, 解析器、码流过滤器

03  av_register_all();      初始化libavformat并注册所有的muxer, demuxer和协议

/* 处理输入文件的格式 并初始化上下文 */

04  ifmt = av_find_input_format("avc");

05  ic = avformat_alloc_context();

06  avformat_open_input(&ic, input, ifmt, &pAVDictionary);

07  avformat_find_stream_info(ic, NULL);

/* 处理输出文件的格式 并初始化上下文 */

08  ofmt = av_guess_format("mpegts", NULL, NULL);

09  oc   = avformat_alloc_context();

10  oc->oformat = ofmt;

/* 将输入文件的音视频流映射到输出文件,并初始化 */

11  int video_index = -1, audio_index = -1;

12  unsigned int i;

13  for (i = 0; i < ic->nb_streams && (video_index < 0 || audio_index < 0); i++){

14    switch (ic->streams[i]->codec->codec_type){

15      case AVMEDIA_TYPE_VIDEO:

16        video_index = i;

17        ic->streams[i]->discard = AVDISCARD_NONE;

18        video_st = add_output_stream(oc, ic->streams[i]);

19        break;

20      case AVMEDIA_TYPE_AUDIO:

21        audio_index = i;

22        ic->streams[i]->discard = AVDISCARD_NONE;

23        audio_st = add_output_stream(oc, ic->streams[i]);

24        break;

25      default:

26        ic->streams[i]->discard = AVDISCARD_ALL;

27        break;

28    }

29  }

30  codec = avcodec_find_decoder(video_st->codec->codec_id); 查找输出视频流的解码器;

31  avcodec_open(video_st->codec, codec);    使用codec初始化上下文video_st->codec;

32  avio_open(&oc->pb, output, AVIO_FLAG_WRITE);  打开输出文件

33  avformat_write_header(oc, &pAVDictionary);    将MPEG2-TS流的头写到输出文件

34  AVBitStreamFilterContext* bsfc =  av_bitstream_filter_init("h264_mp4toannexb"); 初始化流过滤器上下文

35  int decode_done = 0;

36  do{

double segment_time = 0;

AVPacket packet;

37    decode_done = av_read_frame(ic, &packet);   从输入文件中读取一帧

38    if (decode_done < 0)

break;

39    if (av_dup_packet(&packet) < 0){            包数据空间扩展

printf("Call av_dup_packet function failed\n");

av_free_packet(&packet);

break;

}

40    static int nCount = 0;                      前20个包的流信息输出

if (nCount++ < 20){

printf("The packet.stream_index is %ld\n", packet.stream_index);

}

41    if (packet.stream_index == video_index){    计算视频流的时间戳

42      if (packet.pts != (u_int)AV_NOPTS_VALUE){ 计算PTS值

packet.pts      = av_rescale_q(packet.pts,ic->streams[video_index]->time_base,video_st->time_base);

}

43      if (packet.dts != (u_int)AV_NOPTS_VALUE){ 计算DTS值

packet.dts      = av_rescale_q(packet.dts,ic->streams[video_index]->time_base,video_st->time_base);

}

}

44    nRet = av_interleaved_write_frame(oc, &packet); 将数据包混合插入输出文件

45    if (nRet < 0){

printf("Call av_interleaved_write_frame function failed\n");

}

46    else if (nRet > 0)

{

printf("End of stream requested\n");

av_free_packet(&packet);                      释放包

break;

}

47    av_free_packet(&packet);

48  }while(!decode_done);

49  av_write_trailer(oc);       写MPEG-TS流的结尾

50  av_bitstream_filter_close(bsfc);      释放所有的资源

avcodec_close(video_st->codec);

unsigned int k;

for(k = 0; k < oc->nb_streams; k++)

{

av_freep(&oc->streams[k]->codec);

av_freep(&oc->streams[k]);

}

av_free(ic);

av_free(oc);

51  getchar();             等待用户输出任意字符结束

return 0;

}

三、其它

1. 编译选项

# gcc tsmuxer.c -g -o tsmuxer

-I/YOUR_SDK_INSTALL_PATH/include -L/YOUR_SDK_INSTALL_PATH/lib

-lavformat -lavdevice -lavcodec  -lavutil -lavfilter -pthread -ldl -lswscale -lbz2 -lasound

-lmp3lame -lfaac -lx264 -lrtmp -lz -lm

2. 完整代码下载

http://download.csdn.net/detail/fireroll/7292853

FFmpeg SDK开发模型之三:muxer,布布扣,bubuko.com

时间: 2024-10-05 07:58:25

FFmpeg SDK开发模型之三:muxer的相关文章

FFmpeg SDK开发模型之一:解码器

简介 本例讲解了如何使用ffmpeg SDK解码媒体文件: 参考源码是ffmpeg 自带的apiexample.c 一.源代码 #include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #ifdef HAVE_AV_CONFIG_H #undef HAVE_AV_CONFIG_H #endif #include "libavcodec/avcodec.h

FFmpeg SDK开发模型之中的一个:解码器

简单介绍 本例解说了怎样使用ffmpeg SDK解码媒体文件: 參考源代码是ffmpeg 自带的apiexample.c 一.源代码#include <stdlib.h>#include <stdio.h>#include <string.h>#include <math.h> #ifdef HAVE_AV_CONFIG_H#undef HAVE_AV_CONFIG_H#endif #include "libavcodec/avcodec.h&qu

基于FFMPEG SDK流媒体开发1---解码媒体文件流信息

最近项目涉及到流媒体等开发,由于有过开发经验深知其难度所在,没办法只能重新拾起,最新版的SDK被改的一塌糊涂,不过大体的开发思路都是一样的,看多少书查多少资料都无用,一步一步的编写代码 才是学好的关键.. 我会把每一天的学习经过,更新到博文上,希望能给更多想学习的人带来帮助,篇尾附上工程     以及最新版本SDK. FFMPEG被大多数的人命令行来使用,其实在真正的流媒体开发中,要想灵活运用其开发流媒体应用层序,必须使用官方SDK开发  ,实际上我们市面上好多产品 都是基于FFMPEG,比如

【FFMpeg视频开发与应用基础】五、调用FFMpeg SDK封装音频和视频为视频文件

<FFMpeg视频开发与应用基础--使用FFMpeg工具与SDK>视频教程已经在"CSDN学院"上线,视频中包含了从0开始逐行代码实现FFMpeg视频开发的过程,欢迎观看!链接地址:FFMpeg视频开发与应用基础--使用FFMpeg工具与SDK 工程代码地址:FFmpeg_Tutorial 音频和视频的封装过程为解封装的逆过程,即将独立的音频数据和视频数据按照容器文件所规定的格式封装为一个完整的视频文件的过程.对于大多数消费者来说,视频封装的容器是大家最为熟悉的,因为它直接

基于FFMPEG SDK流媒体开发1---解码媒体文件流信息(转)

最近项目涉及到流媒体等开发,由于有过开发经验深知其难度所在,没办法只能重新拾起,最新版的SDK被改的一塌糊涂,不过大体的开发思路都是一样的,看多少书查多少资料都无用,一步一步的编写代码 才是学好的关键.. 我会把每一天的学习经过,更新到博文上,希望能给更多想学习的人带来帮助,篇尾附上工程     以及最新版本SDK. FFMPEG被大多数的人命令行来使用,其实在真正的流媒体开发中,要想灵活运用其开发流媒体应用层序,必须使用官方SDK开发  ,实际上我们市面上好多产品 都是基于FFMPEG,比如

【FFMpeg视频开发与应用基础】四、调用FFmpeg SDK解析封装格式的视频为音频流和视频流

<FFMpeg视频开发与应用基础--使用FFMpeg工具与SDK>视频教程已经在"CSDN学院"上线,视频中包含了从0开始逐行代码实现FFMpeg视频开发的过程,欢迎观看!链接地址:FFMpeg视频开发与应用基础--使用FFMpeg工具与SDK 工程代码地址:FFmpeg_Tutorial 我们平常最常用的音视频文件通常不是单独的音频信号和视频信号,而是一个整体的文件.这个文件会在其中包含音频流和视频流,并通过某种方式进行同步播放.通常,文件的音频和视频通过某种标准格式进行

几大开发模型区别与联系

开发模型分别有瀑布模型,快速原型模型,增量模型,螺旋模型.  瀑布模型,是一种分工很细,力求每个环节都做到最好,前一个环节没做完不进入下一阶段的一种开发模型.就好比建房子,从设计图开始,确定后打地基,砌外墙,然后是里面每个小房间的建设.可是,瀑布模型有一个不好的地方,就是一旦前面的环节出错了,后面环节发现后得从该环节修改开始.这就增大了每个环节的严谨性.就好像设计图错了,建到一半的大楼就得停工或者是重做.  快速原型模型,是一种用建立原型的方法来明确软件需求的开发模型.在一些设计上,可能客户也不

TortoiseSVN安装以及淘宝 TAE SDK 开发环境的搭建

1.进入TortoiseSVN 官网下载地址http://tortoisesvn.net/downloads.html,根据自己的操作系统位数下载相应最新版本的TortoiseSVN. 2.如果你的英文不太过关,建议你同时下载TortoiseSVN 对应的“Chinese, simplified(简体中文语言包)”. 3.双击下载好的“TortoiseSVN-1.8.10.26129-x64-svn-1.8.11”,以默认选项安装SVN.完成后,双击“LanguagePack_1.8.10.26

【转】微信公众账号 Senparc.Weixin.MP SDK 开发教程 索引

微信公众账号 Senparc.Weixin.MP SDK 开发教程 索引 Senparc.Weixin.MP SDK从一开始就坚持开源的状态,这个过程中得到了许多朋友的认可和支持. 目前SDK已经达到比较稳定的版本,这个过程中我觉得有必要整理一些思路和经验,和大家一起分享.也欢迎大家的补充! SDK还在不断优化升级中,开源项目见:https://github.com/JeffreySu/WeiXinMPSDK 微信技术交流社区:http://www.weiweihi.com/QA Senparc