libavcodec на носителе полностью в памяти - PullRequest
0 голосов
/ 11 января 2019

Я имею дело с небольшими микро-видео, которые существуют полностью в памяти (в виде строки). До сих пор я не смог заставить 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);
}

Но это всегда segfaults в find_stream_info.

Я также пытался предварительно демодулировать видеопоток в raw h264 и просто отправлять потоковые пакеты (например,):

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

Но это просто дает неописуемую «ошибку при декодировании MB # #, bytestream #». Обратите внимание, что я удалил проверку ошибок из allocs и т. Д., Чтобы упростить код, но я проверяю, чтобы убедиться, что все правильно распределено и создано.

Любые предложения о том, где мое недоразумение или неправильное использование avcodec?

...