Obtenga el perfil de la secuencia de vídeo MPEG-4 mediante programación en Android
¿Hay alguna manera de obtener el código de perfil de MPEG-4 video fils usando la API estándar de Android?
Los códigos de perfil de ejemplo son: baseline
, main
, high
y así sucesivamente.
- Búsqueda precisa de video
- Android MediaExtractor y la corriente mp3
- Cómo puedo extraer datos rtsp en MediaCodec
- El método onFrameAvailable () de SurfaceTexture siempre se llama demasiado tarde
- Tiempo de muestra / tiempo de presentación incoherente durante la descodificación de vídeo
No quiero incluir ffmpeg
binario en la aplicación de Android sólo para obtener esta información.
Encontré la referencia de la lista de perfiles en la clase MediaCodecInfo.CodecProfileLevel . ¿Puede cualquier organismo confirmar si este es el que debería usar?
Aquí hay un ejemplo de captura de pantalla de información de video tomada desde la aplicación MX Player
- UPDATE # 1: Miré en la aplicación MX Player, parece que utilizan
ffmpeg
binario, así que puedo decir con seguridad que utilizan para extraer elprofile-code
. - UPDATE # 2: También miré en ExoPlayer v1 API, también no parece tener API específica para obtener esta información.
- MediaMuxer no puede hacer MP4 que son streamable
- Descodificación de archivos de audio y re-codificación al formato PCM deseado: 44,100 kHz, 2 canales, 16 bits
- Utilice MediaCodec y MediaExtractor para decodificar y codificar vídeo
- Cómo reducir la latencia en la decodificación de video / avc de MediaCodec
El código de perfil se puede encontrar usando MediaExtractor
Según la documentación de la API , parece que el código de perfil de codificación sólo está disponible desde el nivel 24 de API (Nougat) y hacia arriba.
Aquí está el método que escribí para extraer el código de perfil, no dude en modificar para satisfacer su necesidad.
/** * Get video profile-code from video file. * * @param videoFilePath Path of the video file. * @return One of predefined AVC profiles from {@link MediaCodecInfo.CodecProfileLevel} when found, or {@code -1} if * Android API level does not support extracting profile data. */ @TargetApi(21) public int getVideoEncodingProfile(final String videoFilePath) { int videoProfileCode = -1; File inputFile = new File(videoFilePath); if (!inputFile.canRead()) { throw new RuntimeException("Unable to read " + inputFile); } MediaExtractor mediaExtractor = new MediaExtractor(); // Initialize MediaExtractor and configure/extract video information try { mediaExtractor.setDataSource(inputFile.toString()); } catch (IOException e) { Log.e(TAG, "Unable to set MediaExtractor source.", e); throw new RuntimeException("Unable to set source."); } MediaFormat videoMediaFormat = findVideoMediaFormat(mediaExtractor); // MediaCodecInfo.CodecProfileLevel of the video track if (videoMediaFormat != null && videoMediaFormat.containsKey(MediaFormat.KEY_PROFILE)) { videoProfileCode = videoMediaFormat.getInteger(MediaFormat.KEY_PROFILE); } else { // Current API level does not support encoding profile information. Log.w(TAG, "Video profile code is not supported by current API level."); } mediaExtractor.release(); mediaExtractor = null; return videoProfileCode; } /** * Find video MediaFormat from MediaExtractor. * * @param mediaExtractor The MediaExtractor which is used to find video track. * @return MediaFormat for video track, or {@code null} when video track is not found. */ private MediaFormat findVideoMediaFormat(final MediaExtractor mediaExtractor) { MediaFormat videoTrackMediaFormat = null; int totalTracks = mediaExtractor.getTrackCount(); for (int i = 0; i < totalTracks; i++) { MediaFormat trackFormat = mediaExtractor.getTrackFormat(i); if ((trackFormat.containsKey(MediaFormat.KEY_MIME) && trackFormat.getString(MediaFormat.KEY_MIME).contains("video")) || (trackFormat.containsKey(MediaFormat.KEY_WIDTH) && trackFormat.containsKey(MediaFormat.KEY_HEIGHT)) ) { videoTrackMediaFormat = trackFormat; break; } } return videoTrackMediaFormat; }
Y aquí está un ejemplo de código sobre cómo usarlo.
String TAG = "DEBUG"; // Define your tag int profileCode = getVideoEncodingProfile(videoInfo.getLocalVideoPath()); switch (profileCode) { case MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline: Log.d(TAG, "getVideoEncodingProfile() returned AVCProfileBaseline"); break; case MediaCodecInfo.CodecProfileLevel.AVCProfileMain: Log.d(TAG, "getVideoEncodingProfile() returned AVCProfileMain"); break; case MediaCodecInfo.CodecProfileLevel.AVCProfileExtended: Log.d(TAG, "getVideoEncodingProfile() returned AVCProfileExtended"); break; case MediaCodecInfo.CodecProfileLevel.AVCProfileHigh: Log.d(TAG, "getVideoEncodingProfile() returned AVCProfileHigh"); break; case MediaCodecInfo.CodecProfileLevel.AVCProfileHigh10: Log.d(TAG, "getVideoEncodingProfile() returned AVCProfileHigh10"); break; case MediaCodecInfo.CodecProfileLevel.AVCProfileHigh422: Log.d(TAG, "getVideoEncodingProfile() returned AVCProfileHigh422"); break; case MediaCodecInfo.CodecProfileLevel.AVCProfileHigh444: Log.d(TAG, "getVideoEncodingProfile() returned AVCProfileHigh444"); break; default: Log.d(TAG, "getVideoEncodingProfile() returned unsupported profile code or code not found."); }
Espero eso ayude. Si tienes otra forma que soporte al menos Jelly Bean API nivel 16
déjame saber.
Para referencia, aquí hay una instantánea de MediaFormat
de una pista de vídeo tomada desde el dispositivo Nougat 7.1.1
. (NOTA: API de nivel inferior devolverá menos atributos)
Otras referencias:
- Obtener información de archivo de vídeo desde la aplicación de escritorio – ¿Cómo obtener información de vídeo h264?