是否可以让 MediaCodec 根据流数据进行自我配置?

Is it possible to make MediaCodec to configure itself from the stream data?

我需要使用 MediaCodec 来解码在线流媒体音频(例如 Shoutcast)。
问题是我没有关于流格式的信息。我唯一能从 Stream 的 Response Headers 得到的是 MIME/Content Type.
MediaCodec 应在调用 MediaCodec::start() 之前配置。 MediaFormat 对象应该以某种方式填写。但是是否可以让 MediaCodec 从流数据中配置自己?
或者我该怎么办?

人们,如果你认为这个问题太宽泛,请发表评论,让我知道我到底应该改变什么。只是将其标记为 "Too broad" 并不能说明任何问题。

流媒体、音频或视频通常以 'container' 格式流式传输,例如 mp4、avi、mp3 等

这些容器将包含 header 描述容器内各个流的信息,包括它们编码的编解码器。

如果您熟悉 ffmpeg,则可以使用关联的探测工具 ffprobe 查看 mp4 并查看流。视频文件的示例输出是:

ffprobe version 3.3.1 Copyright (c) 2007-2017 the FFmpeg developers
  built with llvm-gcc 4.2.1 (LLVM build 2336.11.00)
  configuration: --prefix=/Volumes/Ramdisk/sw --enable-gpl --enable-pthreads --enable-version3 --enable-libspeex --enable-libvpx --disable-decoder=libvpx --enable-libmp3lame --enable-libtheora --enable-libvorbis --enable-libx264 --enable-avfilter --enable-libopencore_amrwb --enable-libopencore_amrnb --enable-filters --enable-libgsm --enable-libvidstab --enable-libx265 --disable-doc --arch=x86_64 --enable-runtime-cpudetect
  libavutil      55. 58.100 / 55. 58.100
  libavcodec     57. 89.100 / 57. 89.100
  libavformat    57. 71.100 / 57. 71.100
  libavdevice    57.  6.100 / 57.  6.100
  libavfilter     6. 82.100 /  6. 82.100
  libswscale      4.  6.100 /  4.  6.100
  libswresample   2.  7.100 /  2.  7.100
  libpostproc    54.  5.100 / 54.  5.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'BigBuckBunny_320x180.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: mp41
    creation_time   : 1970-01-01T00:00:00.000000Z
    title           : Big Buck Bunny
    artist          : Blender Foundation
    composer        : Blender Foundation
    date            : 2008
    encoder         : Lavf52.14.0
  Duration: 00:09:56.46, start: 0.000000, bitrate: 867 kb/s
    Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 320x180 [SAR 1:1 DAR 16:9], 702 kb/s, 24 fps, 24 tbr, 24 tbn, 48 tbc (default)
    Metadata:
      creation_time   : 1970-01-01T00:00:00.000000Z
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 159 kb/s (default)
    Metadata:
      creation_time   : 1970-01-01T00:00:00.000000Z
      handler_name    : SoundHandler

您可以在各自的流中看到音频和视频编解码器。

在 Android 上播放音频或视频流的最简单方法是使用 MediaPlayer,因为它将负责查看容器并选择正确的编解码器等:https://developer.android.com/reference/android/media/MediaPlayer.html

我猜这出于某种原因不能满足您的需求,因此您很可能想先使用 MediaExtractor,然后再使用 MediaCodec。

MediaExtractor 'extracts' 容器中的轨道,这样你就可以用它做任何你想做的事。在撰写本文时 (https://developer.android.com/reference/android/media/MediaExtractor.html) 的文档页面上有一个很好的示例,转载于此:

MediaExtractor extractor = new MediaExtractor();
 extractor.setDataSource(...);
 int numTracks = extractor.getTrackCount();
 for (int i = 0; i < numTracks; ++i) {
   MediaFormat format = extractor.getTrackFormat(i);
   String mime = format.getString(MediaFormat.KEY_MIME);
   if (weAreInterestedInThisTrack) {
     extractor.selectTrack(i);
   }
 }
 ByteBuffer inputBuffer = ByteBuffer.allocate(...)
 while (extractor.readSampleData(inputBuffer, ...) >= 0) {
   int trackIndex = extractor.getSampleTrackIndex();
   long presentationTimeUs = extractor.getSampleTime();
   ...
   extractor.advance();
 }

 extractor.release();
 extractor = null;