是否可以让 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;
我需要使用 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;