2015-11-26 2 views
0

Вопрос: Почему я ... Я имею в виду, что происходит с моим декодером? Он всегда возвращает время ожидания (-1), когда я пытаюсь получить его сочные выходные данные!Проблемы с декодером MediaCodec с вызовом dequeueOutputBuffer (H.264)

Позвольте мне сказать, что я прочитал относительные темы, но все еще не могу решить проблему. Мне действительно нужно некоторое руководство и помощь здесь. Хорошо, поэтому то, что я делаю, это передача данных, закодированных AVC, на мой декодер. Кодер работает, вытягивая данные из предварительного просмотра камеры, где я делаю преобразование с NV21 на NV12, прежде чем перейти к кодировщику.

Первые данные, доступные в кодере, имеют codec-specific-data, которые я передаю в функцию ConfigureDecoder(ByteBuffer csd0, ByteBuffer csd1) для создания и настройки декодера, который не вызывает никаких ошибок.

public void ConfigureDecoder(ByteBuffer csd0, ByteBuffer csd1) 
{ 
    try 
    { 
     decoder = MediaCodec.createDecoderByType(MIME_TYPE); 
    } 
    catch(IOException e) 
    { 
     Log.d(TAG, "Decoder codec creation failed: " + e.toString()); 
    } 

    MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, 320, 240); 
    format.setByteBuffer("csd-0", csd0); 
    format.setByteBuffer("csd-1", csd1); 
    decoder.configure(format, null, null, 0); 

    try 
    { 
     decoder.start(); 
     Log.d(TAG, "Decoder configured"); 
    } 
    catch(CodecException e) 
    { 
     Log.d(TAG, "Decoder config start failed: " + e.getDiagnosticInfo()); 
    } 
} 

Следующая функция вызывается один раз кодер уведомляет, что есть кодированные данные доступны (после данных конкретного кодека). Во-первых, я получаю доступный буфер ввода декодера, в случае успеха заполняю его закодированными данными (проверенными) и добавляю их в очередь декодирования. Тогда все идет в ад, я пытаюсь извлечь данные из декодера, используя dequeueOutputBuffer(bufferInfo, 0);, который всегда возвращает -1.


public void offerDecoder(byte[] input, int offset, int size, long presentationTimeUs, int flags) 
{ 
    int inputBufIndex = decoder.dequeueInputBuffer(10000); 
    Log.d(TAG, "Decoder dequeueInputBuffer = " + inputBufIndex); 

    if(inputBufIndex >= 0) 
    { 
     try 
     { 
      // Get valid buffer and push into the decoder input buffer 
      ByteBuffer inputBuf = decoder.getInputBuffer(inputBufIndex); 
      inputBuf.clear(); 
      inputBuf = ByteBuffer.wrap(input); 
      decoder.queueInputBuffer(inputBufIndex, 0, size, presentationTimeUs, flags); 
     } 
     catch(MediaCodec.CodecException ce) 
     { 
      Log.d(TAG, "Decoder adding data error: " + ce.getDiagnosticInfo()); 
     } 
    } 

    MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); 
    int outIndex = decoder.dequeueOutputBuffer(bufferInfo, 0); 
    Log.d(TAG, "Decoder dequeueOutputBuffer = " + outIndex); 

    switch(outIndex) 
    { 
     case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED: 
      ByteBuffer outputBuffers = decoder.getOutputBuffer(outIndex); 
      Log.d(TAG, "Decoder dequeueOutputBuffer = INFO_OUTPUT_BUFFERS_CHANGED"); 
      break; 

     case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED: 
      //MediaFormat bufferFormat = decoder.getOutputFormat(outIndex); 
      Log.d(TAG, "Decoder dequeueOutputBuffer = INFO_OUTPUT_FORMAT_CHANGED"); 
      break; 

     case MediaCodec.INFO_TRY_AGAIN_LATER: 
      //Total fail, something is really wrong if you are always receiving -1 from dequeueOutputBuffer 
      //Log.d(TAG, "Decoder dequeueOutputBuffer = INFO_TRY_AGAIN_LATER"); 
      break; 

     default: 
      Log.d(TAG, "Decoder out buffer info-->" + bufferInfo.offset + "--" + bufferInfo.size + "--" + bufferInfo.flags + "--" + bufferInfo.presentationTimeUs); 
      ByteBuffer buffer = decoder.getOutputBuffer(outIndex); 
      decoder.releaseOutputBuffer(outIndex, false); 
      break; 
    } 
} 

Если ваш достиг этой точки в посте я очень ценю ваше время :)

ответ

1

Кажется, что здесь речь идет о том, что API дает иллюзию, что декодирование будет синхронным - это нет.

Когда вы передадите декодеру один входной пакет, он начнет декодировать его - теперь вы проверяете его только один раз сразу после этого, когда декодер возвращает -1, указывая на то, что он еще не имеет выхода (пока).

Вы можете увеличить параметр timeoutUs, чтобы он подождал немного дольше, чтобы увидеть, что декодер что-то возвращает, или установите его на -1, чтобы ждать бесконечно.

Но если вы всегда ждете выхода сразу для каждого входного пакета, вы получите довольно плохую производительность (и в случае сломанного ввода вы можете вообще не получать какой-либо вывод); вы должны предоставить декодеру столько данных, которые вы должны декодировать до сих пор (пока dequeueInputBuffer не укажет, что в настоящий момент нет доступных буферов ввода) и использовать любые выходные буферы, которые предоставляет декодер. Если для вас подходит только таргетинг на Android 5.0 и выше, вы должны изучить API обратного вызова (MediaCodec.setCallback), что намного более понятно с этим, не имея необходимости опроса для вывода.

+0

IIRC, кодеки AVC хотят, чтобы их подавали около четырех блоков доступа, прежде чем они начнут что-либо делать. Я ожидаю, что это изменится между устройствами. http://bigflake.com/mediacodec/ – fadden

Смежные вопросы