• ffmpeg代码实现自定义encoder


    1、概述

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

    2、代码

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

    3、解释

    原理和前面的自定义的muxer、demuxer一样,在这里就不多说了。
    from:http://blog.csdn.net/dancing_night/article/details/46360851
  • 相关阅读:
    黑芝麻智能技术
    景嘉微GPU与显卡
    电子表格文档控件DevExpress Office File API v21.1
    WPF界面控件Telerik UI for WPF初级入门教程
    WPF应用程序的交互界面还有这些样式,赶紧Get
    手把手教你创建一个Windows风格的应用程序界面(Part 1)
    Web应用的数据管理教程
    Visual Studio插件CodeRush正式发布v21.1.5,免费高速下载
    Mysqldump 备份说明及数据库备份脚本分享-运维笔记
    某国有银行的超融合技术选型和应用实践
  • 原文地址:https://www.cnblogs.com/lidabo/p/7324944.html
Copyright © 2020-2023  润新知