2016-02-04 2 views
0

Я использую API MediaCodec для декодирования видеопотока H264 с использованием SurfaceView в качестве выходной поверхности. Декодер успешно настроен без каких-либо ошибок. Когда я пытаюсь наконец сделать декодированный видеокадр на SurfaceView, используя releaseOutputBuffer(bufferIndex, true), он выдает MediaCodec.CodecException, однако видео отображается правильно.Android MediaCodec releaseOutputBuffer выдает MediaCodec.CodecException при декодировании видео H264

Вызов getDiagnosticInfo() и getErrorCode() на объект исключения возвращает код ошибки -34, но я не могу найти в документах, что означает этот код ошибки. Документация также очень неясна о том, когда это исключение выбрано.

Перед тем, как кто-либо сталкивался с этим кодом исключения/ошибки? Как я могу это исправить?

PS: Несмотря на то, что видео работает отлично, но это исключение бросается при каждом вызове releaseOutputBuffer(bufferIndex, true),.

ответ

-1

Это, скорее всего, проблема с кодеком, который вы используете. Попробуйте использовать что-то вроде этого, чтобы

private static MediaCodecInfo selectCodec(String mime){ 
    int numCodecs = MediaCodecList.getCodecCount(); 

    for(int i = 0; i < numCodecs; i++){ 
     MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); 
     if(!codecInfo.isEncoder()){ 
      continue; 
     } 

     String[] types = codecInfo.getSupportedTypes(); 
     for(int j = 0; j < types.length; j++){ 
      if(types[j].equalsIgnoreCase(mime)){ 
       return codecInfo; 
      } 
     } 
    } 
    return null; 
} 

А затем установить свой датчик с:

MediaCodecInfo codecInfo = selectCodec(MIME_TYPE); 
mEncoder = MediaCodec.createCodecByName(codecInfo.getName()); 

Это может устранить ошибку, гарантируя, что кодек вы выбрали полностью поддерживается.

+0

Это не устраняет проблему. –

+0

Есть ли что-нибудь, что может быть выведено из кода ошибки -34? –

+0

К сожалению, не могу найти. Возможно, вам придется просмотреть источник MediaCodec, чтобы найти, где -34 выбрано внутри этого кода. – Devsil

0

Android-кодек для Android сильно зависит от поставщика устройства. Samsung невероятно проблематичен, другие устройства, работающие с одним и тем же кодом, будут работать нормально. Это была моя жизнь последние 6 месяцев.

Лучший способ сделать, хотя он может чувствовать себя неправильно, это попробовать + уловить + повторить попытку. Есть 4 различных места, где MediaCodec будет генерировать исключения:

  1. Конфигурация - NativeDecoder.Configure (...);
  2. Start - NativeDecoder.Start();
  3. Render output - NativeDecoder.ReleaseOutputBuffer (...);
  4. Ввод - codec.QueueInputBuffer (...);

ПРИМЕЧАНИЕ: мой код находится в Xamarin, но карты вызовов очень близко к raw java.

Способ настройки формата также имеет значение. Mediacodec может привести к сбою на NEXUS устройств, если вы не указываете:

formatDescription.SetInteger(MediaFormat.KeyMaxInputSize, currentPalette.Width * currentPalette.Height); 

Когда вы ловите любое исключение вам нужно будет обеспечить mediacodec сбрасывается. Unfortunatly сброса Isnt доступны для старых API-уровня, но вы можете имитировать тот же эффект с:

#region Close + Release Native Decoder 

    void StopAndReleaseNativeDecoder() { 
     FlushNativeDecoder(); 
     StopNativeDecoder(); 
     ReleaseNativeDecoder(); 
    } 

    void FlushNativeDecoder() { 
     if (NativeDecoder != null) { 
      try { 
       NativeDecoder.Flush(); 
      } catch { 
       // ignore 
      } 
     } 
    } 

    void StopNativeDecoder() { 
     if (NativeDecoder != null) { 
      try { 
       NativeDecoder.Stop(); 
      } catch { 
       // ignore 
      } 
     } 
    } 

    void ReleaseNativeDecoder() { 
     while (NativeDecoder != null) { 
      try { 
       NativeDecoder.Release(); 
      } catch { 
       // ignore 
      } finally { 
       NativeDecoder = null; 
      } 
     } 
    } 

    #endregion 

После того, как вы ловите ошибки при передаче нового входа вы можете проверить:

if (!DroidDecoder.IsRunning && streamView != null && streamView.VideoLayer.IsAvailable) { 
     DroidDecoder.StartDecoder(streamView.VideoLayer.SurfaceTexture); 
} 

DroidDecoder.DecodeH264FrameBuffer(payload, payloadSize, frameDuration, presentationTime, isKeyFrame); 

рендеринга в текстуру В настоящее время просмотр является наиболее стабильным вариантом. Но фрагментация устройства действительно повредила андроид в этой области. Мы нашли более дешевые устройства, такие как Tesco Hudl, которые были самыми стабильными для видео.Даже было до 21 одновременных видео на экране в 1 раз. Samsung S4 может обойтись 4-6 в зависимости от разрешения/fps, но что-то вроде HTC может работать так же, как и Hudl. Это был звонок для пробуждения и заставил меня понять, что устройства samsung буквально копируют дизайн яблока и скручиваются с android-sdk и фактически нарушают много функциональности на этом пути.

+0

@redbain Я согласен с вашими наблюдениями. Samsung, как правило, самый неустойчивый. Они полностью нарушили реализацию OpenMAX в Android 5.0. –

+0

В моем случае исключение MediaCodec генерируется при каждом вызове ReleaseOutputBuffer. Поэтому я не думаю, что перезапуск декодера после каждого кадра является опцией. –

+0

@ nangal.vivek вы разбираете сегменты NALU? Вы должны проанализировать наши сегменты nalu в своем потоке и убедиться, что они находятся в приложении. который равен 0x00,0x00,0x00,0x01, . Это может быть проблема. Я не знаю, можете ли вы использовать медиа-экстрактор для этого, в моем случае мы анализируем сетевой фид в реальном времени. – redbrain

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