簡體   English   中英

FFMPEG I / O輸出緩沖區

[英]FFMPEG I/O output buffer

我目前在嘗試將原始H264 nal數據包封裝到mp4容器中時遇到問題。 但是,我想將結果存儲在內存中,而不是將它們寫入磁盤。 使用libavcodec在mpegts容器中遵循這種方法原始H264幀但到目前為止還沒有成功。

首先,這是寫入內存的正確方法嗎? 我的標題中有一個小結構

struct IOOutput {
    uint8_t* outBuffer;
    int bytesSet;
};

我初始化緩沖區和bytesset。 然后我初始化我的AVIOContext變量

AVIOContext* pIOCtx = avio_alloc_context(pBuffer, iBufSize, 1, outptr, NULL, write_packet, NULL);

其中outptr是指向IOOutput輸出的void指針,write_packet如下所示

int write_packet (void *opaque, uint8_t *buf, int buf_size) {
    IOOutput* out = reinterpret_cast<IOOutput*>(opaque);
    memcpy(out->outBuffer+out->bytesSet, buf, buf_size);
    out->bytesSet+=buf_size;
    return buf_size;
}

我接着說

fc->pb = pIOCtx;
fc->flags = AVFMT_FLAG_CUSTOM_IO;

在我的AVFormatContext * fc變量上。

然后,每當我從幀中編碼nal數據包時,我通過av_interleaved_write_frame將它們寫入AVFormatContext,然后通過以下方式獲取mp4內容

void getBufferContent(char* buffer) {
    memcpy(buffer, output.outBuffer, output.bytesSet);
    output.bytesSet=0;
}

因此重置變量bytesSet,因此在下一次寫操作期間,將在緩沖區的開頭插入字節。 有一個更好的方法嗎? 這實際上是一種有效的方法嗎? 如果我只調用av_interleaved_write_frame和avformat_write_header來添加數據包,FFMPEG是否會執行任何讀取操作?

非常感謝你提前!

編輯

這是關於多路復用過程的代碼 - 在我的編碼功能中我有類似的東西

int frame_size = x264_encoder_encode(obj->mEncoder, &obj->nals, &obj->i_nals, obj->pic_in, obj->pic_out);
int total_size=0;

for(int i=0; i<obj->i_nals;i++)
    {
        if ( !obj->fc ) {
            obj->create( obj->nals[i].p_payload, obj->nals[i].i_payload );
        } 

        if ( obj->fc ) {
            obj->write_frame( obj->nals[i].p_payload, obj->nals[i].i_payload);
        }
    }

// Here I get the output values
int currentBufferSize = obj->output.bytesSet;
char* mem = new char[currentBufferSize];
obj->getBufferContent(mem);

而create和write函數看起來像這樣

int create(void *p, int len) {

   AVOutputFormat *of = av_guess_format( "mp4", 0, 0 );

   fc = avformat_alloc_context();

   // Add video stream
   AVStream *pst = av_new_stream( fc, 0 );
   vi = pst->index;

   void* outptr = (void*) &output;

// Create Buffer
   pIOCtx = avio_alloc_context(pBuffer, iBufSize, 1, outptr, NULL, write_packet, NULL);

   fc->oformat = of;
   fc->pb = pIOCtx;
   fc->flags = AVFMT_FLAG_CUSTOM_IO;

   pcc = pst->codec;

   AVCodec c= {0};
   c.type= AVMEDIA_TYPE_VIDEO;

   avcodec_get_context_defaults3( pcc, &c );
   pcc->codec_type = AVMEDIA_TYPE_VIDEO;

   pcc->codec_id = codec_id;
   pcc->bit_rate = br;
   pcc->width = w;
   pcc->height = h;
   pcc->time_base.num = 1;
   pcc->time_base.den = fps;
}

void write_frame( const void* p, int len ) {

   AVStream *pst = fc->streams[ vi ];

   // Init packet
   AVPacket pkt;
   av_init_packet( &pkt );
   pkt.flags |= ( 0 >= getVopType( p, len ) ) ? AV_PKT_FLAG_KEY : 0;   
   pkt.stream_index = pst->index;
   pkt.data = (uint8_t*)p;
   pkt.size = len;

   pkt.dts = AV_NOPTS_VALUE;
   pkt.pts = AV_NOPTS_VALUE;

   av_interleaved_write_frame( fc, &pkt );

}

請參閱AVFormatContext.pb文檔。 你設置正確,但你不應該觸摸AVFormatContext.flags。 另外,請確保在調用avformat_write_header()之前進行設置。

當你說“它不起作用”時,究竟什么不起作用? 是不是調用了回調? 它中的數據是不是預期的類型/格式? 別的什么? 如果您只想寫原始數據包,那么您可以直接從編碼器(在AVPacket中)獲取編碼數據,這是原始數據。 如果您直接使用libx264的api,它甚至可以單獨為您提供每個nal,因此您無需解析它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM