简体   繁体   English

FFMPEG I / O输出缓冲区

[英]FFMPEG I/O output buffer

I'm currently having issues trying to encapsulate raw H264 nal packets into a mp4 container. 我目前在尝试将原始H264 nal数据包封装到mp4容器中时遇到问题。 Instead of writing them to disk however, I want to have the result stored in memory. 但是,我想将结果存储在内存中,而不是将它们写入磁盘。 I followed this approach Raw H264 frames in mpegts container using libavcodec but haven't been successful so far. 使用libavcodec在mpegts容器中遵循这种方法原始H264帧但到目前为止还没有成功。

First, is this the right way to write to memory? 首先,这是写入内存的正确方法吗? I have a small struct in my header 我的标题中有一个小结构

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

where I initialize the buffer and bytesset. 我初始化缓冲区和bytesset。 I then initialize my AVIOContext variable 然后我初始化我的AVIOContext变量

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

where outptr is a void pointer to IOOutput output, and write_packet looks like the following 其中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;
}

I then set 我接着说

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

on my AVFormatContext *fc variable. 在我的AVFormatContext * fc变量上。

Then, whenever I encode the nal packets I have from a frame, I write them to the AVFormatContext via av_interleaved_write_frame and then get the mp4 contents via 然后,每当我从帧中编码nal数据包时,我通过av_interleaved_write_frame将它们写入AVFormatContext,然后通过以下方式获取mp4内容

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

and thus reset the variable bytesSet, so during the next writing operation bytes will be inserted at the start of the buffer. 因此重置变量bytesSet,因此在下一次写操作期间,将在缓冲区的开头插入字节。 Is there a better way to do this? 有一个更好的方法吗? Is this actually a valid way to do it? 这实际上是一种有效的方法吗? Does FFMPEG do any reading operation if I only do call av_interleaved_write_frame and avformat_write_header in order to add packets? 如果我只调用av_interleaved_write_frame和avformat_write_header来添加数据包,FFMPEG是否会执行任何读取操作?

Thank you very much in advance! 非常感谢你提前!

EDIT 编辑

Here is the code regarding the muxing process - in my encode Function I have something like 这是关于多路复用过程的代码 - 在我的编码功能中我有类似的东西

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);

And the create and write functions look like this 而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 );

}

See the AVFormatContext.pb documentation. 请参阅AVFormatContext.pb文档。 You set it correctly, but you shouldn't touch AVFormatContext.flags. 你设置正确,但你不应该触摸AVFormatContext.flags。 Also, make sure you set it before calling avformat_write_header(). 另外,请确保在调用avformat_write_header()之前进行设置。

When you say "it doesn't work", what exactly doesn't work? 当你说“它不起作用”时,究竟什么不起作用? Is the callback not invoked? 是不是调用了回调? Is the data in it not of the expected type/format? 它中的数据是不是预期的类型/格式? Something else? 别的什么? If all you want to do is write raw nal packets, then you could just take encoded data directly from the encoder (in the AVPacket), that's the raw nal data. 如果您只想写原始数据包,那么您可以直接从编码器(在AVPacket中)获取编码数据,这是原始数据。 If you use libx264's api directly, it even gives you each nal individually so you don't need to parse it. 如果您直接使用libx264的api,它甚至可以单独为您提供每个nal,因此您无需解析它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM