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


     相关博客列表 :

        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 ",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 ",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 ", 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 ");  
      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 ");  
      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 ");  
      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 ", 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 ");  
      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 ", 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 ", 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 ");  
      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 ");  
      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 ", stream_index);  
      246.         av_log(NULL, AV_LOG_DEBUG, "Going to reencode the frame ");  
      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 size:%d pts:%lld ",packet.size,packet.pts);  
      267.   
      268.         if (ret < 0) {  
      269.             av_frame_free(&frame);  
      270.             av_log(NULL, AV_LOG_ERROR, "Decoding failed ");  
      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 size:%d pts:%lld ",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 ",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 ");  
      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 ");  
      344.     return (ret? 1:0);  
      345. }  
    1. from:http://blog.csdn.net/li_wen01/article/details/64905959
  • 相关阅读:
    D3D中的渲染状态简介
    D3D HOOK实现透视讲解
    引入外部文件的时候为什么省略http:
    hbase java Api练习
    [待解决]ColumnPrefixFilter 不能过滤出全部满足条件的,
    代码风格
    eclipse不自动弹出提示的解决办法(eclipse alt+/快捷键失效)centos 6.7
    hbase练习题
    hive安装
    脚本 sh 和 ./ 的区别,exec和source
  • 原文地址:https://www.cnblogs.com/lidabo/p/7346245.html
Copyright © 2020-2023  润新知