11

Есть ли способ получить MPEG-4 видеофайлы profile-code с использованием стандартного API Android?Получите профиль видеопотока MPEG-4 программно на Android

Образец профайлов: baseline, main, high и так далее.

Я не хочу включать ffmpeg двоичный файл в приложение для Android, чтобы получить эту информацию.

Я нашел ссылку на список профилей в категории MediaCodecInfo.CodecProfileLevel. Может ли какой-либо орган подтвердить, является ли это тот, который я должен использовать?

Вот пример скриншот видео Информация взята из MX игрока приложение Sample data with video profile


  • UPDATE # 1: Я посмотрел в приложение MX-плеер, выглядит как они используют ffmpeg бинарным, так что я могут с уверенностью сказать, что они используют это для извлечения profile-code.
  • ОБНОВЛЕНИЕ # 2: Я также рассмотрел API-интерфейсы ExoPlayer v1, у них также нет специального API для получения этой информации.

ответ

1

код профиля можно найти с помощью MediaExtractor

Основываясь на API documentation, кажется, что кодирование профиль-код доступен только от уровня API 24 (нуга) и выше.

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

/** 
* 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; 
} 

И вот пример кода о том, как его использовать.

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."); 

} 

Надеюсь, это поможет. Если у вас есть другой способ, который поддерживает не менее Jelly Bean Уровень API 16 дайте мне знать.


Для справки, вот снимок MediaFormat видеоинформации дорожки, взятая из Нуги7.1.1 устройства. (Примечание: Нижний уровень API будет возвращать меньше атрибутов)

MediaFormat Hash Map - Snapshot

Другие ссылки:

  • Получить информацию видеофайла из настольного приложения - How to get h264 video info?
Смежные вопросы