DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

 相关博客列表 :

    FFMPEG内存操作(一) avio_reading.c 回调读取数据到内存解析 

    FFMPEG内存操作(二)从内存中读取数及数据格式的转换 

    FFmpeg内存操作(三)内存转码器

 

    本文代码来自于自雷霄骅的《最简单的基于FFmpeg的内存读写的例子:内存转码器》 

 

[objc] view plain copy
 
 print?
    1. /** 
    2.  * This software convert video bitstream (Such as MPEG2) to H.264 
    3.  * bitstream. It read video bitstream from memory (not from a file), 
    4.  * convert it to H.264 bitstream, and finally output to another memory. 
    5.  * It's the simplest example to use FFmpeg to read (or write) from  
    6.  * memory. 
    7.  * 
    8.  */  
    9.   
    10. #include <stdio.h>  
    11. #define __STDC_CONSTANT_MACROS  
    12.   
    13. #include "avcodec.h"  
    14. #include "avformat.h"  
    15. #include "avutil.h"  
    16. #include "opt.h"  
    17. #include "pixdesc.h"  
    18. #include "mathematics.h"  
    19.   
    20. FILEFILE *fp_open;  
    21. FILEFILE *fp_write;  
    22.   
    23. //Read File  
    24. int read_buffer(voidvoid *opaque, uint8_t *buf, int buf_size){  
    25.     int true_size;  
    26.   
    27.     if(!feof(fp_open)){  
    28.         true_size=fread(buf,1,buf_size,fp_open);  
    29.         printf("read_buffer buf_size = %d\n",buf_size);  
    30.         return true_size;  
    31.     }else{  
    32.         return -1;  
    33.     }  
    34. }  
    35.   
    36. //Write File  
    37. int write_buffer(voidvoid *opaque, uint8_t *buf, int buf_size){  
    38.     int true_size;  
    39.   
    40.     if(!feof(fp_write)){  
    41.         true_size=fwrite(buf,1,buf_size,fp_write);  
    42.         printf("write_buffer buf_size = %d\n",buf_size);  
    43.         return true_size;  
    44.     }else{  
    45.         return -1;  
    46.     }  
    47. }  
    48.   
    49.   
    50. int flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index)  
    51. {  
    52.     int ret;  
    53.     int got_frame;  
    54.     AVPacket enc_pkt;  
    55.     if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &  
    56.                 CODEC_CAP_DELAY))  
    57.         return 0;  
    58.     while (1) {  
    59.         av_log(NULL, AV_LOG_INFO, "Flushing stream #%u encoder\n", stream_index);  
    60.         //ret = encode_write_frame(NULL, stream_index, &got_frame);  
    61.         enc_pkt.data = NULL;  
    62.         enc_pkt.size = 0;  
    63.         av_init_packet(&enc_pkt);  
    64.         ret = avcodec_encode_video2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,  
    65.                 NULL, &got_frame);  
    66.         av_frame_free(NULL);  
    67.         if (ret < 0)  
    68.             break;  
    69.         if (!got_frame)  
    70.         {ret=0;break;}  
    71.         /* prepare packet for muxing */  
    72.         enc_pkt.stream_index = stream_index;  
    73.         enc_pkt.dts = av_rescale_q_rnd(enc_pkt.dts,  
    74.                 fmt_ctx->streams[stream_index]->codec->time_base,  
    75.                 fmt_ctx->streams[stream_index]->time_base,  
    76.                 //(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
    77.                 (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
    78.         enc_pkt.pts = av_rescale_q_rnd(enc_pkt.pts,  
    79.                 fmt_ctx->streams[stream_index]->codec->time_base,  
    80.                 fmt_ctx->streams[stream_index]->time_base,  
    81.                 (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
    82.                 //(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
    83.         enc_pkt.duration = av_rescale_q(enc_pkt.duration,  
    84.                 fmt_ctx->streams[stream_index]->codec->time_base,  
    85.                 fmt_ctx->streams[stream_index]->time_base);  
    86.         av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n");  
    87.         /* mux encoded frame */  
    88.         ret = av_write_frame(fmt_ctx, &enc_pkt);  
    89.         if (ret < 0)  
    90.             break;  
    91.     }  
    92.     return ret;  
    93. }  
    94.   
    95.   
    96. int main(int argc, char* argv[])  
    97. {  
    98.     int ret;  
    99.     AVFormatContext* ifmt_ctx=NULL;  
    100.     AVFormatContext* ofmt_ctx=NULL;  
    101.     AVIOContext *avio_in=NULL;  
    102.     AVIOContext *avio_out=NULL;  
    103.     unsigned char* inbuffer=NULL;  
    104.     unsigned char* outbuffer=NULL;  
    105.     AVFrame *frame = NULL;  
    106.     AVPacket packet;  
    107.     AVPacket enc_pkt;  
    108.   
    109.     AVStream *out_stream;  
    110.     AVStream *in_stream;  
    111.     AVCodecContext *dec_ctx;   
    112.     AVCodecContext *enc_ctx;  
    113.     AVCodec *encoder;  
    114.   
    115.     AVStream *stream;  
    116.     AVCodecContext *codec_ctx;  
    117.       
    118.     enum AVMediaType type;  
    119.     unsigned int stream_index;  
    120.     unsigned int i=0;  
    121.     int got_frame;  
    122.     int enc_got_frame;  
    123.   
    124.   
    125.     fp_open = fopen("cuc60anniversary_start.ts", "rb"); //视频源文件   
    126.     fp_write=fopen("cuc60anniversary_start.h264","wb+"); //输出文件  
    127.   
    128.     av_register_all();  
    129.     ifmt_ctx=avformat_alloc_context();                                 /* Allocate an AVFormatContext. */  
    130.     avformat_alloc_output_context2(&ofmt_ctx, NULL, "h264", NULL);     /*  Allocate an AVFormatContext for an output format. */  
    131.   
    132.   
    133.     inbuffer=(unsigned char*)av_malloc(32768);  
    134.     outbuffer=(unsigned char*)av_malloc(32768);  
    135.   
    136.     /*open input file*/  
    137.     avio_in =avio_alloc_context(inbuffer, 32768,0,NULL,read_buffer,NULL,NULL);    
    138.     if(avio_in==NULL)  
    139.         goto end;  
    140.     /*open output file*/  
    141.     avio_out =avio_alloc_context(outbuffer, 32768,1,NULL,NULL,write_buffer,NULL);    
    142.     if(avio_out==NULL)  
    143.         goto end;  
    144.       
    145.     ifmt_ctx->pb=avio_in;                                           /* I/O context.    input output context */  
    146.     ifmt_ctx->flags=AVFMT_FLAG_CUSTOM_IO;                           /* The caller has supplied a custom AVIOContext, don't avio_close() it */  
    147.     if ((ret = avformat_open_input(&ifmt_ctx, "whatever", NULL, NULL)) < 0) {  
    148.         av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");  
    149.         return ret;  
    150.     }  
    151.     if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {     /*  Read packets of a media file to get stream information */  
    152.         av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");  
    153.         return ret;  
    154.     }  
    155.     for (i = 0; i < ifmt_ctx->nb_streams; i++) {  
    156.         stream = ifmt_ctx->streams[i];  
    157.         codec_ctx = stream->codec;  
    158.         /* Reencode video & audio and remux subtitles etc. 重新编码视频和音频和翻译字幕等  */  
    159.         if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO){  
    160.             /* Open decoder */  
    161.             /* Initialize the AVCodecContext to use the given AVCodec */  
    162.             ret = avcodec_open2(codec_ctx,  avcodec_find_decoder(codec_ctx->codec_id), NULL);  
    163.             if (ret < 0) {  
    164.                 av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);  
    165.                 return ret;  
    166.             }  
    167.         }  
    168.     }  
    169.     //av_dump_format(ifmt_ctx, 0, "whatever", 0);  
    170.   
    171.   
    172.     //avio_out->write_packet=write_packet;  
    173.     ofmt_ctx->pb=avio_out;   
    174.     ofmt_ctx->flags=AVFMT_FLAG_CUSTOM_IO;  
    175.     for (i = 0; i < 1; i++) {  
    176.         out_stream = avformat_new_stream(ofmt_ctx, NULL);    /*  Add a new stream to a media file. */  
    177.         if (!out_stream) {  
    178.             av_log(NULL, AV_LOG_ERROR, "Failed allocating output stream\n");  
    179.             return AVERROR_UNKNOWN;  
    180.         }  
    181.         in_stream = ifmt_ctx->streams[i];  
    182.         dec_ctx = in_stream->codec;  
    183.         enc_ctx = out_stream->codec;  
    184.         if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)  
    185.         {  
    186.             encoder = avcodec_find_encoder(AV_CODEC_ID_H264);  
    187.             enc_ctx->height = dec_ctx->height;  
    188.             enc_ctx->width = dec_ctx->width;  
    189.             enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio;  
    190.             enc_ctx->pix_fmt = encoder->pix_fmts[0];  
    191.             enc_ctx->time_base = dec_ctx->time_base;  
    192.             //enc_ctx->time_base.num = 1;  
    193.             //enc_ctx->time_base.den = 25;  
    194.             //H264的必备选项,没有就会错  
    195.             enc_ctx->me_range=16;  
    196.             enc_ctx->max_qdiff = 4;  
    197.             enc_ctx->qmin = 10;  
    198.             enc_ctx->qmax = 51;  
    199.             enc_ctx->qcompress = 0.6;   
    200.             enc_ctx->refs=3;  
    201.             enc_ctx->bit_rate = 500000;  
    202.   
    203.             ret = avcodec_open2(enc_ctx, encoder, NULL);  
    204.             if (ret < 0) {  
    205.                 av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i);  
    206.                 return ret;  
    207.             }  
    208.         }  
    209.         else if (dec_ctx->codec_type == AVMEDIA_TYPE_UNKNOWN) {  
    210.             av_log(NULL, AV_LOG_FATAL, "Elementary stream #%d is of unknown type, cannot proceed\n", i);  
    211.             return AVERROR_INVALIDDATA;  
    212.         } else {  
    213.             /* if this stream must be remuxed */  
    214.             /* Copy the settings of the source AVCodecContext into the destination  AVCodecContext */  
    215.             ret = avcodec_copy_context(ofmt_ctx->streams[i]->codec,   ifmt_ctx->streams[i]->codec);  
    216.             if (ret < 0) {  
    217.                 av_log(NULL, AV_LOG_ERROR, "Copying stream context failed\n");  
    218.                 return ret;  
    219.             }  
    220.         }  
    221.         if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)  
    222.             enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;  
    223.     }  
    224.     //av_dump_format(ofmt_ctx, 0, "whatever", 1);  
    225.     /* init muxer, write output file header */  
    226.       
    227.     ret = avformat_write_header(ofmt_ctx, NULL);  
    228.     if (ret < 0) {  
    229.         av_log(NULL, AV_LOG_ERROR, "Error occurred when opening output file\n");  
    230.         return ret;  
    231.     }  
    232.   
    233.     i=0;  
    234.     /* read all packets */  
    235.     while (1) {  
    236.         i++;  
    237.         if ((ret = av_read_frame(ifmt_ctx, &packet)) < 0)   /* Return the next frame of a stream */  
    238.             break;  
    239.           
    240.         stream_index = packet.stream_index;  
    241.         if(stream_index!=0)  
    242.             continue;  
    243.           
    244.         type = ifmt_ctx->streams[packet.stream_index]->codec->codec_type;  
    245.         av_log(NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index %u\n", stream_index);  
    246.         av_log(NULL, AV_LOG_DEBUG, "Going to reencode the frame\n");  
    247.           
    248.         frame = av_frame_alloc();  
    249.         if (!frame) {  
    250.             ret = AVERROR(ENOMEM);  
    251.             break;  
    252.         }  
    253.           
    254.         packet.dts = av_rescale_q_rnd(packet.dts,               /* 解压缩时间戳 */  
    255.             ifmt_ctx->streams[stream_index]->time_base,  
    256.             ifmt_ctx->streams[stream_index]->codec->time_base,  
    257.             //(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
    258.             (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
    259.         packet.pts = av_rescale_q_rnd(packet.pts,              /* 显示时间戳 */  
    260.             ifmt_ctx->streams[stream_index]->time_base,  
    261.             ifmt_ctx->streams[stream_index]->codec->time_base,  
    262.             //(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
    263.             (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
    264.         /* Decode the video frame of size avpkt->size from avpkt->data into picture 解码输入文件 */  
    265.         ret = avcodec_decode_video2(ifmt_ctx->streams[stream_index]->codec, frame, &got_frame, &packet);  
    266.         printf("Decode 1 Packet\tsize:%d\tpts:%lld\n",packet.size,packet.pts);  
    267.   
    268.         if (ret < 0) {  
    269.             av_frame_free(&frame);  
    270.             av_log(NULL, AV_LOG_ERROR, "Decoding failed\n");  
    271.             break;  
    272.         }  
    273.         if (got_frame) {  
    274.             frame->pts = av_frame_get_best_effort_timestamp(frame);  
    275.             frame->pict_type=AV_PICTURE_TYPE_NONE;  
    276.   
    277.             /* Initialize optional fields of a packet with default values */  
    278.             enc_pkt.data = NULL;  
    279.             enc_pkt.size = 0;  
    280.             av_init_packet(&enc_pkt);             
    281.   
    282.             /* Takes input raw video data from frame and writes the next output packet, if available, to avpkt */  
    283.             ret = avcodec_encode_video2 (ofmt_ctx->streams[stream_index]->codec, &enc_pkt, frame, &enc_got_frame);  
    284.             printf("Encode 1 Packet\tsize:%d\tpts:%lld\n",enc_pkt.size,enc_pkt.pts);  
    285.             av_frame_free(&frame);  
    286.             if (ret < 0)  
    287.                 goto end;  
    288.             if (!enc_got_frame)  
    289.                 continue;  
    290.               
    291.             /* prepare packet for muxing */  
    292.             enc_pkt.stream_index = stream_index;  
    293.             enc_pkt.dts = av_rescale_q_rnd(enc_pkt.dts,  
    294.                 ofmt_ctx->streams[stream_index]->codec->time_base,  
    295.                 ofmt_ctx->streams[stream_index]->time_base,  
    296.                 //(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
    297.                 (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
    298.             enc_pkt.pts = av_rescale_q_rnd(enc_pkt.pts,  
    299.                 ofmt_ctx->streams[stream_index]->codec->time_base,  
    300.                 ofmt_ctx->streams[stream_index]->time_base,  
    301.                 //(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
    302.                 (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
    303.             enc_pkt.duration = av_rescale_q(enc_pkt.duration,  
    304.                 ofmt_ctx->streams[stream_index]->codec->time_base,  
    305.                 ofmt_ctx->streams[stream_index]->time_base);  
    306.             av_log(NULL, AV_LOG_INFO, "Muxing frame %d\n",i);  
    307.               
    308.             /* mux encoded frame */  
    309.             /* Write a packet to an output media file */  
    310.             av_write_frame(ofmt_ctx,&enc_pkt);  
    311.             if (ret < 0)  
    312.                 goto end;  
    313.         } else {  
    314.             av_frame_free(&frame);  
    315.         }  
    316.   
    317.         av_free_packet(&packet);  
    318.     }  
    319.   
    320.     /* flush encoders */  
    321.     for (i = 0; i < 1; i++) {  
    322.         /* flush encoder */  
    323.         ret = flush_encoder(ofmt_ctx,i);  
    324.         if (ret < 0) {  
    325.             av_log(NULL, AV_LOG_ERROR, "Flushing encoder failed\n");  
    326.             goto end;  
    327.         }  
    328.     }  
    329.     av_write_trailer(ofmt_ctx);  
    330. end:  
    331.     av_freep(avio_in);  
    332.     av_freep(avio_out);  
    333.     av_free(inbuffer);  
    334.     av_free(outbuffer);  
    335.     av_free_packet(&packet);  
    336.     av_frame_free(&frame);  
    337.     avformat_close_input(&ifmt_ctx);  
    338.     avformat_free_context(ofmt_ctx);  
    339.   
    340.     fclose(fp_open);  
    341.       
    342.     if (ret < 0)  
    343.         av_log(NULL, AV_LOG_ERROR, "Error occurred\n");  
    344.     return (ret? 1:0);  
    345. }  
  1. from:http://blog.csdn.net/li_wen01/article/details/64905959
posted on 2017-08-11 15:38  DoubleLi  阅读(494)  评论(0编辑  收藏  举报