1、概述

本文主要讲述如何用ffmpeg代码实现自己的encoder。

2、代码

  1. /*
  2. *本程序主要实现一个自己的encoder并加入到encoder链中去,供api调用
  3. *作者:缪国凯(MK)
  4. *821486004@qq.com
  5. *2015-6-4
  6. */
  7. #include "stdafx.h"
  8. #ifdef __cplusplus
  9. extern "C"
  10. {
  11. #endif
  12. #include <libavformat/avformat.h>
  13. #include <libavcodec/avcodec.h>
  14. #include <libavutil/pixdesc.h>
  15. #
  16. #ifdef __cplusplus
  17. };
  18. #endif
  19. #pragma comment(lib, "avcodec.lib")
  20. #pragma comment(lib, "avformat.lib")
  21. #pragma comment(lib, "avutil.lib")
  22. //#pragma comment(lib, "avdevice.lib")
  23. //#pragma comment(lib, "avfilter.lib")
  24. //#pragma comment(lib, "postproc.lib")
  25. //#pragma comment(lib, "swresample.lib")
  26. //#pragma comment(lib, "swscale.lib")
  27. static av_cold int mk_encode_init(AVCodecContext *avctx)
  28. {
  29. const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
  30. avctx->coded_frame = av_frame_alloc();
  31. avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
  32. avctx->bits_per_coded_sample = av_get_bits_per_pixel(desc);
  33. if(!avctx->codec_tag)
  34. avctx->codec_tag = avcodec_pix_fmt_to_codec_tag(avctx->pix_fmt);
  35. return 0;
  36. }
  37. static int mk_encode(AVCodecContext *avctx, AVPacket *pkt,
  38. const AVFrame *frame, int *got_packet)
  39. {
  40. int ret = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height);
  41. if (ret < 0)
  42. return ret;
  43. if (pkt->data == NULL && pkt->size == 0)
  44. {
  45. av_new_packet(pkt,ret);
  46. pkt->size = ret;
  47. }
  48. //  if ((ret = ff_alloc_packet2(avctx, pkt, ret)) < 0)
  49. //      return ret;
  50. if ((ret = avpicture_layout((const AVPicture *)frame, avctx->pix_fmt, avctx->width,
  51. avctx->height, pkt->data, pkt->size)) < 0)
  52. return ret;
  53. //  if(avctx->codec_tag == AV_RL32("yuv2") && ret > 0 &&
  54. //      avctx->pix_fmt   == AV_PIX_FMT_YUYV422)
  55. //  {
  56. //          int x;
  57. //          for(x = 1; x < avctx->height*avctx->width*2; x += 2)
  58. //              pkt->data[x] ^= 0x80;
  59. //  }
  60. pkt->flags |= AV_PKT_FLAG_KEY;
  61. *got_packet = 1;
  62. return 0;
  63. }
  64. static av_cold int mk_close(AVCodecContext *avctx)
  65. {
  66. av_frame_free(&avctx->coded_frame);
  67. return 0;
  68. }
  69. AVCodec ff_mkvideo_encoder = {
  70. /*.name           = */"mkvideo",
  71. /*.long_name      = */"mk video",
  72. /*.type           = */AVMEDIA_TYPE_VIDEO,
  73. /*.id             = */AV_CODEC_ID_MKVIDEO,
  74. /*.capabilities = */0,
  75. /*.supported_framerates = */NULL,
  76. /*.pix_fmts     = */NULL,
  77. /*.supported_samplerates = */NULL,
  78. /*.sample_fmts  = */NULL,
  79. /*.channel_layouts = */NULL,
  80. /*.max_lowres       = */0,
  81. /*.priv_class       = */NULL,
  82. /*.profiles     = */NULL,
  83. /*.priv_data_size   = */0,
  84. /*.next         = */NULL,
  85. /*.init_thread_copy = */NULL,
  86. /*.update_thread_context = */NULL,
  87. /*.defaults     = */NULL,
  88. /*.init_static_data = */NULL,
  89. /*.init           = */mk_encode_init,
  90. /*.encode_sub       = */NULL,
  91. /*.encode2        = */mk_encode,
  92. /*.decode           = */NULL,
  93. /*.close          = */mk_close,
  94. };
  95. void help()
  96. {
  97. printf("**********************************************\n");
  98. printf("Usage:\n");
  99. printf("    MyMuxer [inputfile] [outputfile] \n");
  100. printf("\n");
  101. printf("Examples: \n");
  102. printf("    MyMuxer a.avi a.yuv \n");
  103. printf("**********************************************\n");
  104. }
  105. int _tmain(int argc, _TCHAR* argv[])
  106. {
  107. if(argc < 3 || (!strcmp(argv[1],"--help")))
  108. {
  109. help();
  110. return 0;
  111. }
  112. av_register_all();
  113. avcodec_register(&ff_mkvideo_encoder);
  114. AVFormatContext *in_fxt = NULL, *out_fxt = NULL;
  115. AVStream *out_stream = NULL;
  116. int video_index = -1;
  117. if (avformat_open_input(&in_fxt, argv[1], NULL, NULL) < 0)
  118. {
  119. printf("can not open the input file context!\n");
  120. goto end;
  121. }
  122. if (avformat_find_stream_info(in_fxt, NULL) < 0)
  123. {
  124. printf("can not find the stream info!\n");
  125. goto end;
  126. }
  127. if(avformat_alloc_output_context2(&out_fxt, NULL, NULL, argv[2]) < 0)
  128. {
  129. printf("can not alloc output context!\n");
  130. goto end;
  131. }
  132. for (int i = 0; i < in_fxt->nb_streams; i++)
  133. {
  134. if (in_fxt->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
  135. {
  136. //open decoder
  137. if(0 > avcodec_open2(in_fxt->streams[i]->codec, avcodec_find_decoder(in_fxt->streams[i]->codec->codec_id), NULL))
  138. {
  139. printf("can not find or open decoder!\n");
  140. goto end;
  141. }
  142. video_index = i;
  143. //new stream
  144. out_stream = avformat_new_stream(out_fxt, NULL);
  145. if (!out_stream)
  146. {
  147. printf("can not new stream for output!\n");
  148. goto end;
  149. }
  150. //set codec context param
  151. out_stream->codec->codec = avcodec_find_encoder(/*out_fxt->oformat->video_codec*/AV_CODEC_ID_MKVIDEO);
  152. out_stream->codec->height = in_fxt->streams[i]->codec->height;
  153. out_stream->codec->width = in_fxt->streams[i]->codec->width;
  154. out_stream->codec->time_base = in_fxt->streams[i]->time_base;
  155. //out_stream->codec->time_base.den = 25;
  156. out_stream->codec->sample_aspect_ratio = in_fxt->streams[i]->codec->sample_aspect_ratio;
  157. out_stream->codec->pix_fmt = in_fxt->streams[i]->codec->pix_fmt;
  158. out_stream->avg_frame_rate.den = out_stream->codec->time_base.num;
  159. out_stream->avg_frame_rate.num = out_stream->codec->time_base.den;
  160. if (!out_stream->codec->codec)
  161. {
  162. printf("can not find the encoder!\n");
  163. goto end;
  164. }
  165. if ((avcodec_open2(out_stream->codec, out_stream->codec->codec, NULL)) < 0)
  166. {
  167. printf("can not open the encoder\n");
  168. goto end;
  169. }
  170. if (out_fxt->oformat->flags & AVFMT_GLOBALHEADER)
  171. out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
  172. break;
  173. }
  174. }
  175. if (-1 == video_index)
  176. {
  177. printf("found no video stream in input file!\n");
  178. goto end;
  179. }
  180. if (!(out_fxt->oformat->flags & AVFMT_NOFILE))
  181. {
  182. if(avio_open(&out_fxt->pb, argv[2], AVIO_FLAG_WRITE) < 0)
  183. {
  184. printf("can not open output file handle!\n");
  185. goto end;
  186. }
  187. }
  188. if(avformat_write_header(out_fxt, NULL) < 0)
  189. {
  190. printf("can not write the header of the output file!\n");
  191. goto end;
  192. }
  193. AVPacket pkt_in, pkt_out;
  194. AVFrame *frame;
  195. frame = av_frame_alloc();
  196. av_init_packet(&pkt_in);
  197. av_init_packet(&pkt_out);
  198. int got_frame, got_picture;
  199. int i = 0, frame_index = 0;
  200. while(1)
  201. {
  202. got_frame = -1;
  203. got_picture = -1;
  204. if (av_read_frame(in_fxt, &pkt_in) < 0)
  205. {
  206. break;
  207. }
  208. if (avcodec_decode_video2(in_fxt->streams[video_index]->codec, frame, &got_frame, &pkt_in) < 0)
  209. {
  210. printf("can not decoder a frame");
  211. break;
  212. }
  213. av_free_packet(&pkt_in);
  214. if (got_frame)
  215. {
  216. frame->pts = i++;
  217. pkt_out.data = NULL;//主要这里必须自己初始化,或者必须置为null,不然ff_alloc_packet2函数会报错
  218. pkt_out.size = 0;
  219. if (avcodec_encode_video2(out_stream->codec, &pkt_out, frame, &got_picture) < 0)
  220. {
  221. printf("can not encode a frame!\n");
  222. break;
  223. }
  224. if (got_picture)
  225. {
  226. printf("Succeed to encode frame: %5d\tsize:%5d\n",frame_index,pkt_out.size);
  227. pkt_out.stream_index = out_stream->index;
  228. frame_index++;
  229. av_write_frame(out_fxt, &pkt_out);
  230. av_free_packet(&pkt_out);
  231. }
  232. }
  233. }
  234. av_frame_free(&frame);
  235. av_write_trailer(out_fxt);
  236. //clean
  237. avcodec_close(out_stream->codec);
  238. avcodec_close(out_fxt->streams[video_index]->codec);
  239. end:
  240. avformat_close_input(&in_fxt);
  241. if (out_fxt && !(out_fxt->oformat->flags & AVFMT_NOFILE))
  242. {
  243. avio_close(out_fxt->pb);
  244. }
  245. avformat_free_context(out_fxt);
  246. return 0;
  247. }

3、解释

原理和前面的自定义的muxer、demuxer一样,在这里就不多说了。
from:http://blog.csdn.net/dancing_night/article/details/46360851

ffmpeg代码实现自定义encoder的更多相关文章

  1. 自定义Encoder/Decoder进行对象传递

    转载:http://blog.csdn.net/top_code/article/details/50901623 在上一篇文章中,我们使用Netty4本身自带的ObjectDecoder,Objec ...

  2. Netty自定义Encoder/Decoder进行对象传递

    转载:http://blog.csdn.net/top_code/article/details/50901623 在上一篇文章中,我们使用Netty4本身自带的ObjectDecoder,Objec ...

  3. ffmpeg代码笔记2:如何判断MP4文件里面的流是音频还是视频流

    http://blog.csdn.net/qq_19079937/article/details/43191211 在MP4结构体系里面,hdlr字段(具体在root->moov->tra ...

  4. SharePoint 2013 代码实现自定义的站点模版创建Site Collection

    先需要将自定义的站点模版从网站集转移到Farm中. 找一个自己已经完成配置及设计的网站,在网站设置里面选择另存为模版.要注意的是不是所有的站点类型都有另存为模版的功能. 存完之后可在解决方案库的界面里 ...

  5. WF4.0以上使用代码完整自定义动态生成执行工作流Xaml文件

    给大家分享一下,如何完全使用代码自定义的创建生成工作流文件(用代码创建Xaml文件),并且动态加载运行所生成的工作流. 工作流生成后 在Xaml文件里的主要节点如下: 输入输出参数 <x:Mem ...

  6. 一行代码实现自定义转场动画--iOS自定义转场动画集

    WXSTransition 这款非常不错,力推 这是作者源码简书地址: http://www.jianshu.com/p/fd3154946919 这是作者源码github地址 https://git ...

  7. OC开发_代码片段——代码编写自定义的tableViewCell

    一.介绍 之前已经实现过通过简单的XIB文件来自定义我们的tableViewCell,包括每一步的步骤和代码:http://www.cnblogs.com/daomul/p/4355999.html ...

  8. Cordova应用的JavaScript代码和自定义插件代码的调试

    我之前写过三篇Cordova相关的技术文章.当我们使用Cordova将自己开发的前端应用打包安装到手机上后,可能会遇到需要调试Cordova应用的时候. 本文就介绍Cordova应用的调试步骤. 如果 ...

  9. VSCode添加用户代码片段,自定义用户代码片段

    在使用VScode开发中经常会有一些重复使用的代码块,复制粘贴也很麻烦,这时可以在VScode中添加用户代码片段,输入简写即可快捷输入. VScode中添加用户自定义代码片段很简单. 1.在VScod ...

随机推荐

  1. Leetcode - CopyWithRandomList

    Algorithm: Iterate and copy the original list first. For the random pointer, just copy the value fro ...

  2. OpenCV玩耍(一)批量resize一个文件夹里的所有图像

    鉴于用caffe做实验的时候,里面牵扯到一个问题是必须将训练集和测试集都转成256*256的图像,而官网给出的代码又不会用,所以我用opencv转了.其实opencv只转一幅图会很简单,关键在于“批量 ...

  3. 记录-JQuery日历插件My97DatePicker日期范围限制

    对于日期控件,有时会有不能选择今天以前的日期这种需求..... My97DatePicker是一个非常优秀的日历插件,不仅支持多种调用模式,还支持日期范围限制. 常规的调用比较简单,如下所示: 1 & ...

  4. java拾遗1----XML解析(一) DOM解析

    XML解析技术主要有三种: (1)DOM(Document Object Model)文档对象模型:是 W3C 组织推荐的解析XML 的一种方式,即官方的XML解析技术. (2)SAX(Simple ...

  5. IIS架构介绍

    IIS7及以上版本提供的请求-处理架构包括以下内容: Windows Process Activation Service(WAS)可以让站点支持更多协议,不仅仅是HTTP和HTTPS 可以通过增加或 ...

  6. Python菜鸟之路:Python基础-生成器和迭代器、递归

    一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,知道所有的元素被访问完结束.迭代器只能往前不会后退. 1. 迭代器优点 对于无法随机访问的数据结构(比如set)而言, ...

  7. spark的若干问题

    问题1:SPARK与HADOOP之间的关系? spark是一种高效处理hadoop分布式数据的处理引擎.借助hadoop的yarn框架,spark就可以运行在hadoop集群中.同时spark也可以处 ...

  8. ubuntu14.04 在自带python2.7上安装python3.3.5 可以用但是有问题

    一开始写的时候并没有发现这么安装有问题,后来发现问题也不想删了,当个教训,如果想安装从python自带版本换别的版本的话就别接着看了,这么安装有问题.需要进行配置,但是我还不会.其实下面只是差了一步配 ...

  9. maven setting.xml 中文配置详解(全配置)

    春节假期在家养病,乘有时间整理了下之前的知识——知识贵在归纳总结. 参照了官方文档,针对其中的一些未描述详尽的内容翻查了不少资料,补充到了配置文件中,同时再加上一些说明.例子,方便查阅. 内容虽然比较 ...

  10. 【leetcode刷题笔记】Spiral Matrix II

    Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. For ...