我目前在尝试将原始H264 NAL数据包封装到mp4容器中时遇到问题。但是,我希望将结果存储在内存中,而不是将它们写入磁盘。我采用了Raw H264 frames in mpegts container using libavcodec这种方法,但到目前为止还没有成功。
首先,这是写入内存的正确方法吗? header 中有一个小结构
struct IOOutput {
uint8_t* outBuffer;
int bytesSet;
};
我在那里初始化缓冲区和字节集。然后,我初始化AVIOContext变量
AVIOContext* pIOCtx = avio_alloc_context(pBuffer, iBufSize, 1, outptr, NULL, write_packet, NULL);
其中outptr是指向IOOutput输出的空指针,而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变量上。
然后,每当对帧中的最终数据包进行编码时,我都将它们通过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);
创建和写入函数如下所示
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,它甚至可以分别为您提供每个索引,因此您无需解析它。