C++ 媒体上的libavcodec完全在内存中

C++ 媒体上的libavcodec完全在内存中,c++,ffmpeg,libavcodec,C++,Ffmpeg,Libavcodec,我正在处理完全存在于内存中(作为字符串)的小微视频。到目前为止,我还无法让avcodec以这种方式正确解码h264 我尝试了在集装箱媒体上运行的自定义AVIOContext: struct Stream { char* str; size_t pos; size_t size; }; static int ReadStream(void* opaque, uint8* buf, int buf_size) { Stream* strm = reinterpret_cast<Strea

我正在处理完全存在于内存中(作为字符串)的小微视频。到目前为止,我还无法让avcodec以这种方式正确解码h264

我尝试了在集装箱媒体上运行的自定义AVIOContext:

struct Stream { char* str; size_t pos; size_t size; };

static int ReadStream(void* opaque, uint8* buf, int buf_size) {
  Stream* strm = reinterpret_cast<Stream*>(opaque);
  int read = strm->size-strm->pos;
  read = read < buf_size ? read : buf_size;
  memcpy(buf, strm->str+strm->pos, read);
  memset(buf+read, 0, buf_size-read);
  strm->pos += read;
  return read;
}

static int64_t SeekStream(void *opaque, int64_t offset, int whence) {
  Stream* strm = reinterpret_cast<Stream*>(opaque);
  if (whence == AVSEEK_SIZE) {
    return strm->size;
  } else if (whence == SEEK_END) {
    strm->pos = strm->size;
  } else if (whence == SEEK_SET) {
    strm->pos = 0;
  }
  strm->pos += offset;
  return strm->pos;
}

int main(int argc, char *argv[]) {
  string content;
  GetContents("test.mp4", &content);

  avcodec_register_all();

  uint8* buff = (uint8*)malloc(4096 + AV_INPUT_BUFFER_PADDING_SIZE);
  Stream strm = { const_cast<char*>(content.data()), 0, content.size() };
  void* opaque = reinterpret_cast<void*>(&strm);

  AVFormatContext* fmtctx = avformat_alloc_context();
  AVIOContext* avctx = avio_alloc_context(buff, 4096, 0, opaque, &ReadStream, nullptr, &SeekStream);
  AVInputFormat* ifmt = av_find_input_format("mp4");
  AVDictionary* opts = nullptr;

  fmtctx->pb = avctx;
  avformat_open_input(&fmtctx, "", ifmt, &opts);
  avformat_find_stream_info(fmtctx, &opts);
}
struct Stream{char*str;size\t pos;size\t size;};
静态整型读取流(void*不透明,uint8*buf,整型buf_大小){
Stream*strm=重新解释铸件(不透明);
int read=strm->size strm->pos;
读取=读取str+strm->pos,read);
memset(buf+read,0,buf_size-read);
strm->pos+=读取;
返回读取;
}
静态int64_t SeekStream(无效*不透明、int64_t偏移、int Where){
Stream*strm=重新解释铸件(不透明);
if(whence==AVSEEK\u大小){
返回strm->size;
}else if(whence==SEEK\u END){
strm->pos=strm->尺寸;
}else if(whence==SEEK\u SET){
strm->pos=0;
}
strm->pos+=偏移量;
返回strm->pos;
}
int main(int argc,char*argv[]){
字符串内容;
GetContents(“test.mp4”、&content);
avcodec_寄存器_all();
uint8*buff=(uint8*)malloc(4096+AV\u输入\u缓冲\u填充\u大小);
Stream strm={const_cast(content.data()),0,content.size()};
void*不透明=重新解释铸件(&strm);
AVFormatContext*fmtctx=avformat_alloc_context();
AVIOContext*avctx=avio_alloc_上下文(buff、4096、0、不透明、读流、空ptr和SeekStream);
AVInputFormat*ifmt=av_查找_输入_格式(“mp4”);
AVDictionary*opts=nullptr;
fmtctx->pb=avctx;
avformat_open_输入(&fmtctx,“”、ifmt和opts);
avformat_find_stream_info(fmtctx和opts);
}
但这总是在查找流信息时出错

我还尝试将视频流预解复用为原始h264,然后只发送流包(例如):

intmain(intargc,char*argv[]){
字符串内容;
GetContents(“test.h264”和内容);
uint8*data=reinterpret_cast(const_cast(content.c_str());
avcodec_寄存器_all();
AVCodec*codec=AVCodec\u find\u解码器(AV\u codec\u ID\u H264);
AVCodecContext*ctx=avcodec\u alloc\u context3(编解码器);
ctx->宽度=1080;
ctx->高度=1920;
avcodec_open2(ctx、codec、nullptr);
AVPacket*pkt=av_packet_alloc();
AVFrame*frame=av_frame_alloc();
pkt->data=数据;
包装->尺寸=4096;
avcodec_发送_数据包(ctx,pkt);
数据+=4096;
}
但这只是给出了一个难以描述的“解码MB###,bytestream#时的错误”。注意,为了简化代码,我已经从allocs等中删除了错误检查,但我正在检查以确保所有内容都已正确分配和实例化


关于我对avcodec的误解或误用有何建议?

我对libavcodec一无所知,但是我的直觉告诉我,你应该传递一个
nullptr
作为
avformat\u find\u stream\u info
的第二个参数,而不是指向
nullptr
@alesandropower的指针,这是我最近尝试过的。我认为AVDictionary总是以null开头,这就是为什么它作为指向指针的指针传递,然后,无论何时设置值,它都会在必要时实例化。我在想,也许open_input会设置查找流信息可能需要的值,所以我不再给它一个nullptr,而是给它一个avdict。不过,这两种方法都没有任何效果。基于此,您为什么通过test.mp4进入
avformat\u open\u input
?@alesandropower您的意思是什么
test.mp4
作为字符串包装在自定义I/O处理程序中,然后将其作为格式上下文的I/O处理程序附加。然后用
avformat\u open\u输入打开格式上下文
对不起,我打错了。我的意思是问你是不是通过了test.mp4作为
avformat\u open\u input
的文件名?
int main(int argc, char *argv[]) {
  string content;
  GetContents("test.h264", &content);
  uint8* data = reinterpret_cast<uint8*>(const_cast<char*>(content.c_str()));

  avcodec_register_all();

  AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264);
  AVCodecContext* ctx = avcodec_alloc_context3(codec);

  ctx->width = 1080;
  ctx->height = 1920;
  avcodec_open2(ctx, codec, nullptr);

  AVPacket* pkt = av_packet_alloc();    
  AVFrame* frame = av_frame_alloc();

  pkt->data = data;
  pkt->size = 4096;
  avcodec_send_packet(ctx, pkt);
  data += 4096;
}