Смешивание необработанного h264 + aa c в файл mp4 с помощью av_interleaved_write_frame (), возвращающей 0, но видео не воспроизводится - PullRequest
0 голосов
/ 03 апреля 2020

У меня есть программа [1] , которая объединяет аудио и видео в файл mp4 (в отдельном рабочем потоке, извлекая аудио / видеокадр из потокового демона). Звук отлично воспроизводится в VL C, но видео не воспроизводится, журналы отладки VL C показывают, что стартовый код видеокадра не найден.

У меня есть другая программа демультиплексирования [2] чтобы получить весь кадр, чтобы увидеть, что произошло. Я обнаружил, что видеокадр изменен

00000001 674D0029... was modified into 00000019 674D0029... (framesize is 29)
00000001 68EE3C80... was modified into 00000004 68EE3C80... (framesize is 8)
00000001 65888010... was modified into 0002D56F 65888010... (framesize is 185715)
00000001 619A0101... was modified into 00003E1E 619A0101... (framesize is 15906)
00000001 619A0202... was modified into 00003E3C 619A0202... (framesize is 15936)
00000001 619A0303... was modified into 00003E1E 619A0303... (framesize is 15581)

Кажется, что стартовый код h264 был заменен чем-то вроде ... размера кадра. но почему? Есть что-то, что я сделал неправильно? (Есть идеи? Что-то помечено? Инициализация AVPacket? Ошибка в копировании данных AVPacket?)

[1] программа мультиплексирования

int go_on = 1;
std::mutex g_mutex;
AVStream* g_AudioStream = NULL;
AVStream* g_VideoStream = NULL;

int polling_ringbuffer(int stream_type);

int main(int argc, char** argv)
{

  AVFormatContext* pFmtCntx = avformat_alloc_context();
  avio_open(&pFmtCntx->pb, argv[1], AVIO_FLAG_WRITE);
  pFmtCntx->oformat = av_guess_format(NULL, argv[1], NULL);
  g_AudioStream = avformat_new_stream( pFmtCntx, NULL );
  g_VideoStream = avformat_new_stream( pFmtCntx, NULL );
  initAudioStream(g_AudioStream->codecpar);
  initVideoStream(g_VideoStream->codecpar);
  avformat_write_header(pFmtCntx, NULL);

  std::thread audio(polling_ringbuffer, AUDIO_RINGBUFFER);
  std::thread video(polling_ringbuffer, VIDEO_RINGBUFFER);

  audio.join();
  video.join();

  av_write_trailer(pFmtCntx);
  if ( pFmtCntx->oformat && !( pFmtCntx->oformat->flags & AVFMT_NOFILE ) && pFmtCntx->pb )
    avio_close( pFmtCntx->pb );
  avformat_free_context( g_FmtCntx );

  return 0;
}

int polling_ringbuffer(int stream_type)
{
  uint8_t* data = new uint8_t[1024*1024];
  int64_t timestamp = 0;
  int data_len = 0;
  while(go_on)
  {
    const std::lock_guard<std::mutex> lock(g_mutex);
    data_len = ReadRingbuffer(stream_type, data, 1024*1024, &timestamp);

    AVPacket pkt = {0};
    av_init_packet(&pkt);
    pkt.data = data;
    pkt.size = data_len;

    static AVRational r = {1,1000};
    switch(stream_type)
    {
      case STREAMTYPE_AUDIO:
        pkt.stream_index = g_AudioStream->index;
        pkt.flags = 0;
        pkt.pts = av_rescale_q(timestamp, r, g_AudioStream->time_base);
        break;
      case STREAMTYPE_VIDEO:
        pkt.stream_index = g_VIDEOStream->index;
        pkt.flags = isKeyFrame(data, data_len)?AV_PKT_FLAG_KEY:0;
        pkt.pts = av_rescale_q(timestamp, r, g_VideoStream->time_base);
        break;
    }
    static int64_t lastPTS = 0;
    pkt.dts = pkt.pts;
    pkt.duration = (lastPTS==0)? 0 : (pkt.pts-lastPTS);
    lastPTS = pkt.pts;

    int ret = av_interleaved_write_frame(g_FmtCntx, &pkt);
    if(0!=ret)
      printf("[%s:%d] av_interleaved_write_frame():%d\n", __FILE__, __LINE__, ret);
  }

  return 0;
}

[2] программа демультиплексирования

int main(int argc, char** argv)
{
  AVFormatContext* pFormatCtx = avformat_alloc_context();
  AVPacket pkt;
  av_init_packet(&pkt);
  avformat_open_input(&pFormatCtx, argv[1], NULL, NULL);
  for(;;)
  {
    if (av_read_frame(pFormatCtx, &pkt) >= 0)
    {
      printf("[%d] %s (len:%d)\n", pkt.stream_index, BinToHex(pkt.data, MIN(64, pkt.size)), pkt.size );
    }
    else
      break;
  }

  avformat_close_input(&pFormatCtx);
  return 0;
}

[3] Вот мое окружение

Linux MY-RASP-4 4.14.98 #1 SMP Mon Jun 24 12:34:42 UTC 2019 armv7l GNU/Linux
ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 8.2.0 (GCC)

libavutil      56. 22.100 / 56. 22.100
libavcodec     58. 35.100 / 58. 35.100
libavformat    58. 20.100 / 58. 20.100
libavdevice    58.  5.100 / 58.  5.100
libavfilter     7. 40.101 /  7. 40.101
libswscale      5.  3.100 /  5.  3.100
libswresample   3.  3.100 /  3.  3.100
libpostproc    55.  3.100 / 55.  3.100
...