2016-03-15 3 views
1

Ссылка: https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.javaEncodeDecodeMux - Samsung Devices - Испытано на S6 Краю и S5

Я использую приведенный выше код для кодирования/декодирования/MUX для того, чтобы сделать видео с более низким разрешением и битрейтом. Работает отлично на всех разрешениях, включая видео 4k на nexus5, LG g3, один плюс.

Но устройства Samsung показывают неуместное поведение.

  • Если я взять 4k видео (3840x2160) в качестве входных данных и хочу, чтобы понизить его разрешение до 1920х1080 я получаю исключение.

  • Если я беру 4k видео (3840x2160) в качестве входных данных и хочу снизить его разрешение до 1280x720, я все равно получаю исключение.

  • Он отлично работает, если я установил целевое разрешение 640x360.

Я думаю, это может быть связано с проблемами кодеков на устройствах samsung.

Ниже приведен фрагмент кода

MediaCodec encoder = MediaCodec.createByCodecName(codecInfo.getName()); 
     encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); 
     surfaceReference.set(encoder.createInputSurface()); 
     encoder.start(); 

    MediaCodec decoder = MediaCodec.createDecoderByType(getMimeTypeFor(inputFormat)); 
     decoder.configure(inputFormat, surface, null, 0); 
decoder.start(); 

После утверждение вызывает, за исключением

decoder.configure(inputFormat, surface, null, 0); 

Ниже приведен трассировки стека

I/ACodec: [OMX.Exynos.AVC.Encoder] Now Executing 
03-15 14:35:23.801 25357-26008/com.test I/ACodec: [] Now uninitialized 
03-15 14:35:23.801 25357-26036/com.test I/OMXClient: Using client-side OMX mux. 
03-15 14:35:23.811 25357-26036/com.test I/ACodec: can't find wfdsink-exynos-enable 
03-15 14:35:23.811 25357-26036/com.test E/ACodec: configureCodec multi window instance fail appPid : 25357 
03-15 14:35:23.811 25357-26036/com.test E/ACodec: [OMX.Exynos.avc.dec] configureCodec returning error -1021 
03-15 14:35:23.811 25357-26036/com.test E/ACodec: signalError(omxError 0x80001001, internalError -1021) 
03-15 14:35:23.811 25357-26035/com.test E/MediaCodec: Codec reported err 0xfffffc03, actionCode 0, while in state 3 
03-15 14:35:23.811 25357-26008/com.test E/MediaCodec: configure failed with err 0xfffffc03, resetting... 
03-15 14:35:23.811 25357-26036/com.test I/ACodec: [OMX.Exynos.avc.dec] Now uninitialized 
03-15 14:35:23.811 25357-26008/com.test I/ACodec: [] Now uninitialized 
03-15 14:35:23.811 25357-26036/com.test I/OMXClient: Using client-side OMX mux. 
+1

Samsung - это всегда борьба. Удачи! –

+0

Может быть аппаратным ограничением, например. недостаточная пропускная способность в части кодека для обработки декодирования при 4K и кодирования на 720p. Сообщение об ошибке обычно бесполезно. – fadden

+0

Вы нашли решение этой проблемы? –

ответ

1

В основном, это, кажется, что некоторые устройства Samsung может просто имеют проблемы с декодером Exynos. Я получал почти те же сообщения об ошибках, которые вы видели. Решение было сложным, но, похоже, оно устранило проблему.

я заменил эти 2 строки кода:

decoder = MediaCodec.createDecoderByType(mime); 
decoder.configure(format, surface, null, 0); 

С помощью этого метода:

private MediaCodec configDecoder(MediaFormat format, Surface surface) { 

    if (format == null || surface == null) { 
     return null; 
    } 

    MediaCodec codec; 
    String mime = format.getString(MediaFormat.KEY_MIME); 
    MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS); 
    MediaCodecInfo[] infos = list.getCodecInfos(); 

    for (MediaCodecInfo info : infos) { 

     CodecCapabilities capabilities; 
     boolean formatSupported; 

     // does codec support this mime type 
     try { 
      capabilities = info.getCapabilitiesForType(mime); 
     } catch (IllegalArgumentException ignored) { 
      continue; 
     } 

     // does codec support his video format 
     try { 
      formatSupported = capabilities.isFormatSupported(format); 
     } catch (IllegalArgumentException ignored) { 
      continue; 
     } 

     // can we configure it successfully 
     if (formatSupported) { 
      // try decoder 
      try { 
       codec = MediaCodec.createByCodecName(info.getName()); 
      } catch (IOException e) { 
       continue; 
      } 
      try { 
       codec.configure(format, surface, null, 0); 
      } catch (IllegalArgumentException ignored) { 
       // configure() failed 
       codec.release(); 
       continue; 
      } catch (IllegalStateException ignored) { 
       // configure() failed 
       codec.release(); 
       continue; 
      } 
      // configure() successful 
      return codec; 
     } 
    } // end of for loop 

    // no decoder found 
    return null; 
} 

Обычно, чтобы получить кодек, вы просто звоните

MediaCodec.createDecoderByType(mimeType) 

или

MediaCodecList.findDecoderForFormat(format) 

Но это только дает вам один вариант. Используя вышеописанный метод, у вас есть более подробный контроль над кодеком, который вы используете. Например, вы можете легко отфильтровать все Exynos кодеков, добавив

if (!info.getName().contains("Exynos")) 

или что-то подобное.

В любом случае, надеюсь, это поможет кому-то еще в будущем. Это расстроило меня несколько дней.

В заключительной ноте, мои старые устройства прекрасно работали со старым кодом, и новый код использует некоторый леденец и выше методы, так что мое окончательное решение выглядело так:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { 
    decoder = configDecoder(format, surface); 
} else { 
    decoder = MediaCodec.createDecoderByType(mime); 
    decoder.configure(format, surface, null, 0); 
} 

Наблюдая запуск кода, он по-прежнему использует Exynos большую часть времени, но когда по каким-то причинам сбои configure(), приятно видеть, что он, казалось бы, перешел к следующему кодеку.

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