ffmpeg代码实现自定义encoder
1、概述
2、代码
- /*
- *本程序主要实现一个自己的encoder并加入到encoder链中去,供api调用
- *作者:缪国凯(MK)
- *821486004@qq.com
- *2015-6-4
- */
- #include "stdafx.h"
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- #include <libavformat/avformat.h>
- #include <libavcodec/avcodec.h>
- #include <libavutil/pixdesc.h>
- #
- #ifdef __cplusplus
- };
- #endif
- #pragma comment(lib, "avcodec.lib")
- #pragma comment(lib, "avformat.lib")
- #pragma comment(lib, "avutil.lib")
- //#pragma comment(lib, "avdevice.lib")
- //#pragma comment(lib, "avfilter.lib")
- //#pragma comment(lib, "postproc.lib")
- //#pragma comment(lib, "swresample.lib")
- //#pragma comment(lib, "swscale.lib")
- static av_cold int mk_encode_init(AVCodecContext *avctx)
- {
- const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
- avctx->coded_frame = av_frame_alloc();
- avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
- avctx->bits_per_coded_sample = av_get_bits_per_pixel(desc);
- if(!avctx->codec_tag)
- avctx->codec_tag = avcodec_pix_fmt_to_codec_tag(avctx->pix_fmt);
- return 0;
- }
- static int mk_encode(AVCodecContext *avctx, AVPacket *pkt,
- const AVFrame *frame, int *got_packet)
- {
- int ret = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height);
- if (ret < 0)
- return ret;
- if (pkt->data == NULL && pkt->size == 0)
- {
- av_new_packet(pkt,ret);
- pkt->size = ret;
- }
- // if ((ret = ff_alloc_packet2(avctx, pkt, ret)) < 0)
- // return ret;
- if ((ret = avpicture_layout((const AVPicture *)frame, avctx->pix_fmt, avctx->width,
- avctx->height, pkt->data, pkt->size)) < 0)
- return ret;
- // if(avctx->codec_tag == AV_RL32("yuv2") && ret > 0 &&
- // avctx->pix_fmt == AV_PIX_FMT_YUYV422)
- // {
- // int x;
- // for(x = 1; x < avctx->height*avctx->width*2; x += 2)
- // pkt->data[x] ^= 0x80;
- // }
- pkt->flags |= AV_PKT_FLAG_KEY;
- *got_packet = 1;
- return 0;
- }
- static av_cold int mk_close(AVCodecContext *avctx)
- {
- av_frame_free(&avctx->coded_frame);
- return 0;
- }
- AVCodec ff_mkvideo_encoder = {
- /*.name = */"mkvideo",
- /*.long_name = */"mk video",
- /*.type = */AVMEDIA_TYPE_VIDEO,
- /*.id = */AV_CODEC_ID_MKVIDEO,
- /*.capabilities = */0,
- /*.supported_framerates = */NULL,
- /*.pix_fmts = */NULL,
- /*.supported_samplerates = */NULL,
- /*.sample_fmts = */NULL,
- /*.channel_layouts = */NULL,
- /*.max_lowres = */0,
- /*.priv_class = */NULL,
- /*.profiles = */NULL,
- /*.priv_data_size = */0,
- /*.next = */NULL,
- /*.init_thread_copy = */NULL,
- /*.update_thread_context = */NULL,
- /*.defaults = */NULL,
- /*.init_static_data = */NULL,
- /*.init = */mk_encode_init,
- /*.encode_sub = */NULL,
- /*.encode2 = */mk_encode,
- /*.decode = */NULL,
- /*.close = */mk_close,
- };
- void help()
- {
- printf("**********************************************\n");
- printf("Usage:\n");
- printf(" MyMuxer [inputfile] [outputfile] \n");
- printf("\n");
- printf("Examples: \n");
- printf(" MyMuxer a.avi a.yuv \n");
- printf("**********************************************\n");
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- if(argc < 3 || (!strcmp(argv[1],"--help")))
- {
- help();
- return 0;
- }
- av_register_all();
- avcodec_register(&ff_mkvideo_encoder);
- AVFormatContext *in_fxt = NULL, *out_fxt = NULL;
- AVStream *out_stream = NULL;
- int video_index = -1;
- if (avformat_open_input(&in_fxt, argv[1], NULL, NULL) < 0)
- {
- printf("can not open the input file context!\n");
- goto end;
- }
- if (avformat_find_stream_info(in_fxt, NULL) < 0)
- {
- printf("can not find the stream info!\n");
- goto end;
- }
- if(avformat_alloc_output_context2(&out_fxt, NULL, NULL, argv[2]) < 0)
- {
- printf("can not alloc output context!\n");
- goto end;
- }
- for (int i = 0; i < in_fxt->nb_streams; i++)
- {
- if (in_fxt->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
- {
- //open decoder
- if(0 > avcodec_open2(in_fxt->streams[i]->codec, avcodec_find_decoder(in_fxt->streams[i]->codec->codec_id), NULL))
- {
- printf("can not find or open decoder!\n");
- goto end;
- }
- video_index = i;
- //new stream
- out_stream = avformat_new_stream(out_fxt, NULL);
- if (!out_stream)
- {
- printf("can not new stream for output!\n");
- goto end;
- }
- //set codec context param
- out_stream->codec->codec = avcodec_find_encoder(/*out_fxt->oformat->video_codec*/AV_CODEC_ID_MKVIDEO);
- out_stream->codec->height = in_fxt->streams[i]->codec->height;
- out_stream->codec->width = in_fxt->streams[i]->codec->width;
- out_stream->codec->time_base = in_fxt->streams[i]->time_base;
- //out_stream->codec->time_base.den = 25;
- out_stream->codec->sample_aspect_ratio = in_fxt->streams[i]->codec->sample_aspect_ratio;
- out_stream->codec->pix_fmt = in_fxt->streams[i]->codec->pix_fmt;
- out_stream->avg_frame_rate.den = out_stream->codec->time_base.num;
- out_stream->avg_frame_rate.num = out_stream->codec->time_base.den;
- if (!out_stream->codec->codec)
- {
- printf("can not find the encoder!\n");
- goto end;
- }
- if ((avcodec_open2(out_stream->codec, out_stream->codec->codec, NULL)) < 0)
- {
- printf("can not open the encoder\n");
- goto end;
- }
- if (out_fxt->oformat->flags & AVFMT_GLOBALHEADER)
- out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
- break;
- }
- }
- if (-1 == video_index)
- {
- printf("found no video stream in input file!\n");
- goto end;
- }
- if (!(out_fxt->oformat->flags & AVFMT_NOFILE))
- {
- if(avio_open(&out_fxt->pb, argv[2], AVIO_FLAG_WRITE) < 0)
- {
- printf("can not open output file handle!\n");
- goto end;
- }
- }
- if(avformat_write_header(out_fxt, NULL) < 0)
- {
- printf("can not write the header of the output file!\n");
- goto end;
- }
- AVPacket pkt_in, pkt_out;
- AVFrame *frame;
- frame = av_frame_alloc();
- av_init_packet(&pkt_in);
- av_init_packet(&pkt_out);
- int got_frame, got_picture;
- int i = 0, frame_index = 0;
- while(1)
- {
- got_frame = -1;
- got_picture = -1;
- if (av_read_frame(in_fxt, &pkt_in) < 0)
- {
- break;
- }
- if (avcodec_decode_video2(in_fxt->streams[video_index]->codec, frame, &got_frame, &pkt_in) < 0)
- {
- printf("can not decoder a frame");
- break;
- }
- av_free_packet(&pkt_in);
- if (got_frame)
- {
- frame->pts = i++;
- pkt_out.data = NULL;//主要这里必须自己初始化,或者必须置为null,不然ff_alloc_packet2函数会报错
- pkt_out.size = 0;
- if (avcodec_encode_video2(out_stream->codec, &pkt_out, frame, &got_picture) < 0)
- {
- printf("can not encode a frame!\n");
- break;
- }
- if (got_picture)
- {
- printf("Succeed to encode frame: %5d\tsize:%5d\n",frame_index,pkt_out.size);
- pkt_out.stream_index = out_stream->index;
- frame_index++;
- av_write_frame(out_fxt, &pkt_out);
- av_free_packet(&pkt_out);
- }
- }
- }
- av_frame_free(&frame);
- av_write_trailer(out_fxt);
- //clean
- avcodec_close(out_stream->codec);
- avcodec_close(out_fxt->streams[video_index]->codec);
- end:
- avformat_close_input(&in_fxt);
- if (out_fxt && !(out_fxt->oformat->flags & AVFMT_NOFILE))
- {
- avio_close(out_fxt->pb);
- }
- avformat_free_context(out_fxt);
- return 0;
- }
3、解释
ffmpeg代码实现自定义encoder的更多相关文章
- 自定义Encoder/Decoder进行对象传递
转载:http://blog.csdn.net/top_code/article/details/50901623 在上一篇文章中,我们使用Netty4本身自带的ObjectDecoder,Objec ...
- Netty自定义Encoder/Decoder进行对象传递
转载:http://blog.csdn.net/top_code/article/details/50901623 在上一篇文章中,我们使用Netty4本身自带的ObjectDecoder,Objec ...
- ffmpeg代码笔记2:如何判断MP4文件里面的流是音频还是视频流
http://blog.csdn.net/qq_19079937/article/details/43191211 在MP4结构体系里面,hdlr字段(具体在root->moov->tra ...
- SharePoint 2013 代码实现自定义的站点模版创建Site Collection
先需要将自定义的站点模版从网站集转移到Farm中. 找一个自己已经完成配置及设计的网站,在网站设置里面选择另存为模版.要注意的是不是所有的站点类型都有另存为模版的功能. 存完之后可在解决方案库的界面里 ...
- WF4.0以上使用代码完整自定义动态生成执行工作流Xaml文件
给大家分享一下,如何完全使用代码自定义的创建生成工作流文件(用代码创建Xaml文件),并且动态加载运行所生成的工作流. 工作流生成后 在Xaml文件里的主要节点如下: 输入输出参数 <x:Mem ...
- 一行代码实现自定义转场动画--iOS自定义转场动画集
WXSTransition 这款非常不错,力推 这是作者源码简书地址: http://www.jianshu.com/p/fd3154946919 这是作者源码github地址 https://git ...
- OC开发_代码片段——代码编写自定义的tableViewCell
一.介绍 之前已经实现过通过简单的XIB文件来自定义我们的tableViewCell,包括每一步的步骤和代码:http://www.cnblogs.com/daomul/p/4355999.html ...
- Cordova应用的JavaScript代码和自定义插件代码的调试
我之前写过三篇Cordova相关的技术文章.当我们使用Cordova将自己开发的前端应用打包安装到手机上后,可能会遇到需要调试Cordova应用的时候. 本文就介绍Cordova应用的调试步骤. 如果 ...
- VSCode添加用户代码片段,自定义用户代码片段
在使用VScode开发中经常会有一些重复使用的代码块,复制粘贴也很麻烦,这时可以在VScode中添加用户代码片段,输入简写即可快捷输入. VScode中添加用户自定义代码片段很简单. 1.在VScod ...
随机推荐
- c_str()方法使用
语法: const char *c_str(); c_str()函数返回一个指向正规C字符串的指针常量, 内容与本string串相同. 这是为了与c语言兼容,在c语言中没有string类型,故必须通过 ...
- 【BZOJ1109】[POI2007]堆积木Klo 二维偏序
[BZOJ1109][POI2007]堆积木Klo Description Mary在她的生日礼物中有一些积木.那些积木都是相同大小的立方体.每个积木上面都有一个数.Mary用他的所有积木垒了一个高塔 ...
- (转)Java并发编程:阻塞队列
原文地址: http://www.cnblogs.com/dolphin0520/p/3932906.html 一.几种主要的阻塞队列 自从Java 1.5之后,在java.util.concurre ...
- bash编程基础
bash变量 变量命名: 1.不能使用程序中的关键字(保留字) 2.只能使用数字.字母和下划线,且不能以数字开头 3.要见名知义 变量类型: 数值型:精确数值(整数),近似数值(浮点型) 字符型:ch ...
- 浅谈命令查询职责分离(CQRS)模式---转载
在常用的三层架构中,通常都是通过数据访问层来修改或者查询数据,一般修改和查询使用的是相同的实体.在一些业务逻辑简单的系统中可能没有什么问题,但是随着系统逻辑变得复杂,用户增多,这种设计就会出现一些性能 ...
- JS异错面试题
转自 http://www.codeceo.com/article/one-javascript-interview.html function Foo() { getName = function ...
- thymeleaf基本应用
Thymeleaf是个XML/XHTML/HTML5模板引擎,可以用于Web与非Web应用. Thymeleaf的主要目标在于提供一种可被浏览器正确显示的.格式良好的模板创建方式,因此也可以用作静态建 ...
- POJ3094 Sky Code(莫比乌斯反演)
POJ3094 Sky Code(莫比乌斯反演) Sky Code 题意 给你\(n\le 10^5\)个数,这些数\(\le 10^5\),问这些这些数组成的互不相同的无序四元组(a,b,c,d)使 ...
- java基础入门之九九乘法表
/* 自学java 九九乘法表 Power by Stuart Date: 2015.4.23 */public class Math { public static void main (Strin ...
- SAP basis 常用事物
1.创建一个新的用户 完成client创建和拷贝后,在开始正式工作之前,需要创建新的用户. 用这个用户进行工作.默认ddic和sap*用户不要用于实际的业务. 创建用户的过程很简单,只要以su01 ...