天天看點

FFmpeg記憶體操作(三)記憶體轉碼器

 相關部落格清單 :

/** 

 * This software convert video bitstream (Such as MPEG2) to H.264 

 * bitstream. It read video bitstream from memory (not from a file), 

 * convert it to H.264 bitstream, and finally output to another memory. 

 * It's the simplest example to use FFmpeg to read (or write) from  

 * memory. 

 * 

 */  

#include <stdio.h>  

#define __STDC_CONSTANT_MACROS  

#include "avcodec.h"  

#include "avformat.h"  

#include "avutil.h"  

#include "opt.h"  

#include "pixdesc.h"  

#include "mathematics.h"  

FILEFILE *fp_open;  

FILEFILE *fp_write;  

//Read File  

int read_buffer(voidvoid *opaque, uint8_t *buf, int buf_size){  

    int true_size;  

    if(!feof(fp_open)){  

        true_size=fread(buf,1,buf_size,fp_open);  

        printf("read_buffer buf_size = %d\n",buf_size);  

        return true_size;  

    }else{  

        return -1;  

    }  

}  

//Write File  

int write_buffer(voidvoid *opaque, uint8_t *buf, int buf_size){  

    if(!feof(fp_write)){  

        true_size=fwrite(buf,1,buf_size,fp_write);  

        printf("write_buffer buf_size = %d\n",buf_size);  

int flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index)  

{  

    int ret;  

    int got_frame;  

    AVPacket enc_pkt;  

    if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &  

                CODEC_CAP_DELAY))  

        return 0;  

    while (1) {  

        av_log(NULL, AV_LOG_INFO, "Flushing stream #%u encoder\n", stream_index);  

        //ret = encode_write_frame(NULL, stream_index, &got_frame);  

        enc_pkt.data = NULL;  

        enc_pkt.size = 0;  

        av_init_packet(&enc_pkt);  

        ret = avcodec_encode_video2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,  

                NULL, &got_frame);  

        av_frame_free(NULL);  

        if (ret < 0)  

            break;  

        if (!got_frame)  

        {ret=0;break;}  

        /* prepare packet for muxing */  

        enc_pkt.stream_index = stream_index;  

        enc_pkt.dts = av_rescale_q_rnd(enc_pkt.dts,  

                fmt_ctx->streams[stream_index]->codec->time_base,  

                fmt_ctx->streams[stream_index]->time_base,  

                //(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  

                (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  

        enc_pkt.pts = av_rescale_q_rnd(enc_pkt.pts,  

        enc_pkt.duration = av_rescale_q(enc_pkt.duration,  

                fmt_ctx->streams[stream_index]->time_base);  

        av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n");  

        /* mux encoded frame */  

        ret = av_write_frame(fmt_ctx, &enc_pkt);  

    return ret;  

int main(int argc, char* argv[])  

    AVFormatContext* ifmt_ctx=NULL;  

    AVFormatContext* ofmt_ctx=NULL;  

    AVIOContext *avio_in=NULL;  

    AVIOContext *avio_out=NULL;  

    unsigned char* inbuffer=NULL;  

    unsigned char* outbuffer=NULL;  

    AVFrame *frame = NULL;  

    AVPacket packet;  

    AVStream *out_stream;  

    AVStream *in_stream;  

    AVCodecContext *dec_ctx;   

    AVCodecContext *enc_ctx;  

    AVCodec *encoder;  

    AVStream *stream;  

    AVCodecContext *codec_ctx;  

    enum AVMediaType type;  

    unsigned int stream_index;  

    unsigned int i=0;  

    int enc_got_frame;  

    fp_open = fopen("cuc60anniversary_start.ts", "rb"); //視訊源檔案   

    fp_write=fopen("cuc60anniversary_start.h264","wb+"); //輸出檔案  

    av_register_all();  

    ifmt_ctx=avformat_alloc_context();                                 /* Allocate an AVFormatContext. */  

    avformat_alloc_output_context2(&ofmt_ctx, NULL, "h264", NULL);     /*  Allocate an AVFormatContext for an output format. */  

    inbuffer=(unsigned char*)av_malloc(32768);  

    outbuffer=(unsigned char*)av_malloc(32768);  

    /*open input file*/  

    avio_in =avio_alloc_context(inbuffer, 32768,0,NULL,read_buffer,NULL,NULL);    

    if(avio_in==NULL)  

        goto end;  

    /*open output file*/  

    avio_out =avio_alloc_context(outbuffer, 32768,1,NULL,NULL,write_buffer,NULL);    

    if(avio_out==NULL)  

    ifmt_ctx->pb=avio_in;                                           /* I/O context.    input output context */  

    ifmt_ctx->flags=AVFMT_FLAG_CUSTOM_IO;                           /* The caller has supplied a custom AVIOContext, don't avio_close() it */  

    if ((ret = avformat_open_input(&ifmt_ctx, "whatever", NULL, NULL)) < 0) {  

        av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");  

        return ret;  

    if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {     /*  Read packets of a media file to get stream information */  

        av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");  

    for (i = 0; i < ifmt_ctx->nb_streams; i++) {  

        stream = ifmt_ctx->streams[i];  

        codec_ctx = stream->codec;  

        /* Reencode video & audio and remux subtitles etc. 重新編碼視訊和音頻和翻譯字幕等  */  

        if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO){  

            /* Open decoder */  

            /* Initialize the AVCodecContext to use the given AVCodec */  

            ret = avcodec_open2(codec_ctx,  avcodec_find_decoder(codec_ctx->codec_id), NULL);  

            if (ret < 0) {  

                av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);  

                return ret;  

            }  

        }  

    //av_dump_format(ifmt_ctx, 0, "whatever", 0);  

    //avio_out->write_packet=write_packet;  

    ofmt_ctx->pb=avio_out;   

    ofmt_ctx->flags=AVFMT_FLAG_CUSTOM_IO;  

    for (i = 0; i < 1; i++) {  

        out_stream = avformat_new_stream(ofmt_ctx, NULL);    /*  Add a new stream to a media file. */  

        if (!out_stream) {  

            av_log(NULL, AV_LOG_ERROR, "Failed allocating output stream\n");  

            return AVERROR_UNKNOWN;  

        in_stream = ifmt_ctx->streams[i];  

        dec_ctx = in_stream->codec;  

        enc_ctx = out_stream->codec;  

        if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)  

        {  

            encoder = avcodec_find_encoder(AV_CODEC_ID_H264);  

            enc_ctx->height = dec_ctx->height;  

            enc_ctx->width = dec_ctx->width;  

            enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio;  

            enc_ctx->pix_fmt = encoder->pix_fmts[0];  

            enc_ctx->time_base = dec_ctx->time_base;  

            //enc_ctx->time_base.num = 1;  

            //enc_ctx->time_base.den = 25;  

            //H264的必備選項,沒有就會錯  

            enc_ctx->me_range=16;  

            enc_ctx->max_qdiff = 4;  

            enc_ctx->qmin = 10;  

            enc_ctx->qmax = 51;  

            enc_ctx->qcompress = 0.6;   

            enc_ctx->refs=3;  

            enc_ctx->bit_rate = 500000;  

            ret = avcodec_open2(enc_ctx, encoder, NULL);  

                av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i);  

        else if (dec_ctx->codec_type == AVMEDIA_TYPE_UNKNOWN) {  

            av_log(NULL, AV_LOG_FATAL, "Elementary stream #%d is of unknown type, cannot proceed\n", i);  

            return AVERROR_INVALIDDATA;  

        } else {  

            /* if this stream must be remuxed */  

            /* Copy the settings of the source AVCodecContext into the destination  AVCodecContext */  

            ret = avcodec_copy_context(ofmt_ctx->streams[i]->codec,   ifmt_ctx->streams[i]->codec);  

                av_log(NULL, AV_LOG_ERROR, "Copying stream context failed\n");  

        if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)  

            enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;  

    //av_dump_format(ofmt_ctx, 0, "whatever", 1);  

    /* init muxer, write output file header */  

    ret = avformat_write_header(ofmt_ctx, NULL);  

    if (ret < 0) {  

        av_log(NULL, AV_LOG_ERROR, "Error occurred when opening output file\n");  

    i=0;  

    /* read all packets */  

        i++;  

        if ((ret = av_read_frame(ifmt_ctx, &packet)) < 0)   /* Return the next frame of a stream */  

        stream_index = packet.stream_index;  

        if(stream_index!=0)  

            continue;  

        type = ifmt_ctx->streams[packet.stream_index]->codec->codec_type;  

        av_log(NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index %u\n", stream_index);  

        av_log(NULL, AV_LOG_DEBUG, "Going to reencode the frame\n");  

        frame = av_frame_alloc();  

        if (!frame) {  

            ret = AVERROR(ENOMEM);  

        packet.dts = av_rescale_q_rnd(packet.dts,               /* 解壓縮時間戳 */  

            ifmt_ctx->streams[stream_index]->time_base,  

            ifmt_ctx->streams[stream_index]->codec->time_base,  

            //(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  

            (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  

        packet.pts = av_rescale_q_rnd(packet.pts,              /* 顯示時間戳 */  

        /* Decode the video frame of size avpkt->size from avpkt->data into picture 解碼輸入檔案 */  

        ret = avcodec_decode_video2(ifmt_ctx->streams[stream_index]->codec, frame, &got_frame, &packet);  

        printf("Decode 1 Packet\tsize:%d\tpts:%lld\n",packet.size,packet.pts);  

        if (ret < 0) {  

            av_frame_free(&frame);  

            av_log(NULL, AV_LOG_ERROR, "Decoding failed\n");  

        if (got_frame) {  

            frame->pts = av_frame_get_best_effort_timestamp(frame);  

            frame->pict_type=AV_PICTURE_TYPE_NONE;  

            /* Initialize optional fields of a packet with default values */  

            enc_pkt.data = NULL;  

            enc_pkt.size = 0;  

            av_init_packet(&enc_pkt);             

            /* Takes input raw video data from frame and writes the next output packet, if available, to avpkt */  

            ret = avcodec_encode_video2 (ofmt_ctx->streams[stream_index]->codec, &enc_pkt, frame, &enc_got_frame);  

            printf("Encode 1 Packet\tsize:%d\tpts:%lld\n",enc_pkt.size,enc_pkt.pts);  

            if (ret < 0)  

                goto end;  

            if (!enc_got_frame)  

                continue;  

            /* prepare packet for muxing */  

            enc_pkt.stream_index = stream_index;  

            enc_pkt.dts = av_rescale_q_rnd(enc_pkt.dts,  

                ofmt_ctx->streams[stream_index]->codec->time_base,  

                ofmt_ctx->streams[stream_index]->time_base,  

            enc_pkt.pts = av_rescale_q_rnd(enc_pkt.pts,  

            enc_pkt.duration = av_rescale_q(enc_pkt.duration,  

                ofmt_ctx->streams[stream_index]->time_base);  

            av_log(NULL, AV_LOG_INFO, "Muxing frame %d\n",i);  

            /* mux encoded frame */  

            /* Write a packet to an output media file */  

            av_write_frame(ofmt_ctx,&enc_pkt);  

        av_free_packet(&packet);  

    /* flush encoders */  

        /* flush encoder */  

        ret = flush_encoder(ofmt_ctx,i);  

            av_log(NULL, AV_LOG_ERROR, "Flushing encoder failed\n");  

            goto end;  

    av_write_trailer(ofmt_ctx);  

end:  

    av_freep(avio_in);  

    av_freep(avio_out);  

    av_free(inbuffer);  

    av_free(outbuffer);  

    av_free_packet(&packet);  

    av_frame_free(&frame);  

    avformat_close_input(&ifmt_ctx);  

    avformat_free_context(ofmt_ctx);  

    fclose(fp_open);  

    if (ret < 0)  

        av_log(NULL, AV_LOG_ERROR, "Error occurred\n");  

    return (ret? 1:0);  

}  

from:http://blog.csdn.net/li_wen01/article/details/64905959

繼續閱讀