ffmpeg代码实现自定义decoder

来源:互联网 发布:淘宝旺铺装修模板代码 编辑:程序博客网 时间:2024/04/30 13:01

1、概述

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

2、代码

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

3、解释

原理和前面的自定义的muxer、demuxer、encoder一样,在这里就不多说了。
0 0
原创粉丝点击