2016-08-23 4 views
2

Я использую проект, основанный на последней FFmpeg мерзавца исходного дерева, и ссылок на разделяемую DLL файлы, опубликованный на Zeranoe https://ffmpeg.zeranoe.com/builds/Декодирование mp4/мов с помощью FFMPEG терпит неудачу

В воспроизведении кода работает и петли. Он воспроизводит файлы h265 (raw), mpeg, avi и mpg. Однако, как только контейнер mp4 или mkv указан как входной файл, независимо от того, что внутри, из кодека выгружается много ошибок. Неважно, если это HEVC или h264.

[h264 @ 00000000xyz] No start code is found 
[h264 @ 00000000xyz] Error splitting the input into NAL units. 

Чтобы все было действительно странно, ffplay.exe отлично играет в эти файлы.

Я понимаю, что я, вероятно, исправлю это, сначала преобразовывая файлы в необработанный формат, но я хотел бы иметь возможность читать и анализировать файлы mp4, которыми они являются. Поскольку я использую pre-build libs Zeraneo, я предполагаю, что во время сборки что-то не было включено, но тогда я ожидал бы, что ffplay тоже потерпит неудачу. Нужно ли устанавливать флаг в формате format_context или codec_context или предоставлять какой-то идентификатор фильтра?

Фильмы, которые играют отлично пришли из http://bbb3d.renderfarming.net/download.html, http://www.w6rz.net/ и http://www.sample-videos.com/

Эти работы:

big_buck_bunny_480p_surround-fix.avi 
bigbuckbunny_480x272.h265 

Будучи в общей сложности нуб в FFmpeg, пожалуйста, помогите мне понять, что не так и как это исправить. Если pre-build libs являются виновниками, то второй вопрос заключается в том, что у кого-то есть удобная настройка cmake для ее создания для отладки и выпуска целей Windows X64 и x32.

Вот источник для инициализации FFmpeg для чтения

avdevice_register_all(); 
avfilter_register_all(); 
av_register_all(); 
avformat_network_init(); 

Формат разобранную следующим образом:

m_FormatContext = avformat_alloc_context(); 
if (avformat_open_input(&m_FormatContext, file.GetPath().ToString().c_str(), NULL, NULL) != 0) 
{ 
    //std::cout << "failed to open input" << std::endl; 
    success = false; 
} 
// find stream info 
if (success) 
{ 
    if (avformat_find_stream_info(m_FormatContext, NULL) < 0) 
    { 
     //std::cout << "failed to get stream info" << std::endl; 
     success = false; 
    } 
} 

Поток открыт следующим образом:

m_VideoStream = avstream; 
m_FormatContext = formatContext; 
if (m_VideoStream) 
{ 
    m_StreamIndex = m_VideoStream->stream_identifier; 
    AVCodecParameters *codecpar = m_VideoStream->codecpar;  
    if (codecpar) 
    { 
     AVCodecID codec_id = codecpar->codec_id; 
     m_Decoder = avcodec_find_decoder(codec_id); 
     if (m_Decoder) 
     { 
      m_CodecContext = avcodec_alloc_context3(m_Decoder); 
      if (m_CodecContext) 
      { 
       m_CodecContext->width = codecpar->width;      
       m_CodecContext->height = codecpar->height; 
       m_VideoSize = i3(codecpar->width, codecpar->height,1); 
       success = 0 == avcodec_open2(m_CodecContext, m_Decoder, NULL); 
       if (success) 
       { 
        if(m_CodecContext) 
        { 
         int size = av_image_get_buffer_size(format, m_CodecContext->width, m_CodecContext->height, 1);  
         if (size > 0) 
         { 
          av_frame = av_frame_alloc(); 
          gl_frame = av_frame_alloc();   
          uint8_t *internal_buffer = (uint8_t *)av_malloc(size * sizeof(uint8_t)); 
          av_image_fill_arrays((uint8_t**)((AVPicture *)gl_frame->data), (int*) ((AVPicture *)gl_frame->linesize), internal_buffer, format, m_CodecContext->width, m_CodecContext->height,1); 
          m_Packet = (AVPacket *)av_malloc(sizeof(AVPacket)); 
         } 
        } 
       } 
       if (!success) 
       { 
        avcodec_close(m_CodecContext); 
        avcodec_free_context(&m_CodecContext); 
        m_CodecContext = NULL; 
        m_Decoder = NULL; 
        m_VideoStream = NULL; 
       } 
      } 
      else 
      { 
       m_Decoder = NULL; 
       m_VideoStream = NULL; 
      } 
     } 
    } 
} 

и декодирование одна нить:

do 
{ 
    if (av_read_frame(m_FormatContext, m_Packet) < 0) 
    { 
     av_packet_unref(m_Packet); 
     m_AllPacketsSent = true; 
    } 
    else 
    { 
     if (m_Packet->stream_index == m_StreamIndex) 
     {     
      avcodec_send_packet(m_CodecContext, m_Packet); 
     } 
    } 

    int frame_finished = avcodec_receive_frame(m_CodecContext, av_frame); 
    if (frame_finished == 0) 
    { 
     if (!conv_ctx) 
     { 
      conv_ctx = sws_getContext(m_CodecContext->width, 
       m_CodecContext->height, m_CodecContext->pix_fmt, 
       m_CodecContext->width, m_CodecContext->height, format, SWS_BICUBIC, NULL, NULL, NULL); 
     } 

     sws_scale(conv_ctx, av_frame->data, av_frame->linesize, 0, m_CodecContext->height, gl_frame->data, gl_frame->linesize); 

     switch(format) 
     { 
      case AV_PIX_FMT_BGR32_1: 
      case AV_PIX_FMT_RGB32_1: 
      case AV_PIX_FMT_0BGR32: 
      case AV_PIX_FMT_0RGB32: 
      case AV_PIX_FMT_BGR32: 
      case AV_PIX_FMT_RGB32:    
      { 
       m_CodecContext->bits_per_raw_sample = 32; break;      
      } 
      default: 
      { 
       FWASSERT(format == AV_PIX_FMT_RGB32, "The format changed, update the bits per raw sample!"); break; 
      } 
     } 


     size_t bufferSize = m_CodecContext->width * m_CodecContext->height * m_CodecContext->bits_per_raw_sample/8; 
     m_Buffer.Realloc(bufferSize, false, gl_frame->data[0]); 
     m_VideoSize = i3(m_CodecContext->width, m_CodecContext->height,1); 
     result = true; 
     // sends the image buffer straight to the locked texture here.. 
     // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, codec_ctx->width, codec_ctx->height, GL_RGB, GL_UNSIGNED_BYTE, gl_frame->data[0]); 
    } 

    av_packet_unref(m_Packet); 
} while (m_Packet->stream_index != m_StreamIndex); 

m_FrameDecoded = result; 

Любое понимание оценено!

ответ

3

Вместо неявно обеспечивают ширину и высоту здесь:

m_CodecContext->width = codecpar->width;      
m_CodecContext->height = codecpar->height; 

вы должны позвонить avcodec_parameters_to_context().

+0

Да, это исправлено. Так очевидно. Благодаря! – StarShine