11

Czy istnieje sposób na uzyskanie plików wideo MPEG-4 profile-code przy użyciu standardowego interfejsu API Androida?Program do strumienia wideo MPEG-4 programowo na Androidzie

Przykładowe kody profilu: baseline, main, high i tak dalej.

Nie chcę dodawać pliku binarnego ffmpeg w aplikacji na Androida, aby uzyskać te informacje.

Znalazłem odniesienie do listy profili w klasie MediaCodecInfo.CodecProfileLevel. Czy jakiekolwiek ciało może potwierdzić, czy to właśnie powinienem używać?

Oto przykładowy zrzut ekranu z informacją wideo pobrane z MX gracza aplikacji Sample data with video profile


  • Aktualizacja # 1: Spojrzałem w aplikacji MX Player wygląda używają ffmpeg binarny, więc można bezpiecznie powiedzieć, że używają tego do wyodrębnienia profile-code.
  • AKTUALIZACJA # 2: Zajrzałem także do interfejsów API ExoPlayer v1, ale nie mają one również konkretnego API, aby uzyskać te informacje.

Odpowiedz

1

kod profilu można znaleźć za pomocą MediaExtractor

podstawie API documentation wydaje się, że kodowanie profil kodu jest dostępna tylko z poziomu API 24 (nugat) i do góry.

Oto metoda, którą napisałem, aby wyodrębnić kod profilu, zachęcamy do modyfikacji w celu zaspokojenia potrzeb.

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

A oto przykładowy kod, jak go używać.

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

} 

Mam nadzieję, że to pomaga. Jeśli masz inny sposób, który obsługuje co najmniej Jelly Bean poziom API 16 daj mi znać.


Dla porównania, tutaj jest migawką MediaFormat toru wideo pobranych z Nugat7.1.1 urządzenia. (UWAGA: Niższy poziom API powróci mniej atrybutów)

MediaFormat Hash Map - Snapshot

Inne odniesienia:

Powiązane problemy