Android的媒体codeC API - 音乐播放上的模拟器,而不是设备模拟器、音乐播放、而不是、媒体

2023-09-03 23:20:01 作者:思念从前

下面给出的code正常工作在模拟器,而不是设备。我发现,看起来可疑我下面几行:

V / MediaExtractor(5030):自动探测到的媒体内容为音频/ MPEG'有信心0.20 V / ChromiumHTTPDataSource(5030):mContentSize未定义或网络可能会断开连接 V / ChromiumHTTPDataSource(5030):mContentSize未定义或网络可能会断开连接 D / com.example.media codectest(5030):MIME类型:音频/ MPEG

我要寻找的提示/建议。在此先感谢...

 私有类PlayerThread继承Thread {

    @覆盖
    公共无效的run(){
        MediaExtractor提取;
        媒体codeC codeC;
        ByteBuffer的[] codecInputBuffers;
        ByteBuffer的[] codecOutputBuffers;

        AudioTrack mAudioTrack;

        mAudioTrack =新AudioTrack(
                AudioManager.STREAM_MUSIC,
                44100,
                AudioFormat.CHANNEL_OUT_STEREO,
                AudioFormat.ENCODING_PCM_16BIT,
                8192 * 2,
                AudioTrack.MODE_STREAM);

        提取=新MediaExtractor();
        尝试
        {
            extractor.setDataSource(http://anmp3streamingsource.com/stream);
            MediaFormat格式= extractor.getTrackFormat(0);
            字符串哑剧= format.getString(MediaFormat.KEY_MIME);
            Log.d(TAG,的String.Format(MIME类型:%s时,MIME));

            codeC =媒体codec.createDe coderByType(MIME);
            codec.configure(
                    格式,
                    空/ *表面* /,
                    空/ *加密* /,
                    0 / *标志* /);
            codec.start();
            codecInputBuffers = codec.getInputBuffers();
            codecOutputBuffers = codec.getOutputBuffers();

            extractor.selectTrack(0); //< =您必须选择曲目。您将从这条轨道读取样本的媒体!

            布尔sawInputEOS = FALSE;
            布尔sawOutputEOS = FALSE;

            对于 (;;) {
                INT inputBufIndex = codec.dequeueInputBuffer(-1);
                如果(inputBufIndex> = 0){
                    ByteBuffer的dstBuf = codecInputBuffers [inputBufIndex]

                    INT的采样大小= extractor.readSampleData(dstBuf,0);
                    长presentationTimeUs = 0;
                    如果(采样大小℃,){
                        sawInputEOS = TRUE;
                        的采样大小= 0;
                    } 其他 {
                        presentationTimeUs = extractor.getSampleTime();
                    }

                    codec.queueInputBuffer(inputBufIndex,
                                           0,//偏移
                                           采样大小,
                                           presentationTimeUs,
                                           sawInputEOS?媒体codec.BUFFER_FLAG_END_OF_STREAM:0);
                    如果(!sawInputEOS){
                        extractor.advance();
                    }

                    媒体codec.BufferInfo信息=新BufferInfo();
                    最终诠释解析度= codec.dequeueOutputBuffer(资讯,-1);
                    如果(RES> = 0){
                        INT outputBufIndex =资源;
                        ByteBuffer的BUF = codecOutputBuffers [outputBufIndex]

                        最后一个字节[]块=新的字节[info.size]
                        buf.get(块); //读取缓冲区一次全部
                        buf.clear(); // ** 必须做!!!否则,下一次你得到这个相同的缓冲区不好的事情会发生

                        mAudioTrack.play();

                        如果(chunk.length大于0){
                            mAudioTrack.write(组块,0,chunk.length);
                        }
                        codec.releaseOutputBuffer(outputBufIndex,假/ *渲染* /);

                        如果((info.flags&安培;媒体codec.BUFFER_FLAG_END_OF_STREAM)= 0){
                            sawOutputEOS = TRUE;
                        }
                    }
                    否则,如果(RES ==媒体codec.INFO_OUTPUT_BUFFERS_CHANGED)
                    {
                        codecOutputBuffers = codec.getOutputBuffers();
                    }
                    否则,如果(RES ==媒体codec.INFO_OUTPUT_FORMAT_CHANGED)
                    {
                        最后MediaFormat oformat = codec.getOutputFormat();
                        Log.d(TAG,输出格式已更改为+ oformat);
                        mAudioTrack.setPlaybackRate(oformat.getInteger(MediaFormat.KEY_SAMPLE_RATE));
                    }
                 }
            }

        }
        赶上(IOException异常E)
        {
            Log.e(TAG,e.getMessage());
        }
    }
}
 

解决方案

我还没有与声音,但我想我可能会看到这个问题。你挂在 dequeueOutputBuffer()因为codeC在等待更多的输入。

一些视频codeCS的希望〜4缓冲器的输入之前,他们甚至会完成初始化(for例如)。我期待一些音频codeCS可能的行为方式相同。 codeC实现从设备到设备各不相同,所以这并不奇怪,是什么运行在模拟器上的表现多少不同。

从-1更改超时(永远等待)的东西温和(比如1000毫秒)。

The code given below works fine on the emulator, but not the device. I found the following lines that looked suspicious to me:

Android视频开发进阶 Android的Media API

V/MediaExtractor(5030): Autodetected media content as 'audio/mpeg' with confidence 0.20 V/ChromiumHTTPDataSource(5030): mContentSize is undefined or network might be disconnected V/ChromiumHTTPDataSource(5030): mContentSize is undefined or network might be disconnected D/com.example.mediacodectest(5030): MIME TYPE: audio/mpeg

I am looking for hints/suggestions. Thanks in advance...

private class PlayerThread extends Thread {

    @Override
    public void run() {
        MediaExtractor extractor;
        MediaCodec codec;
        ByteBuffer[] codecInputBuffers;
        ByteBuffer[] codecOutputBuffers;

        AudioTrack mAudioTrack;

        mAudioTrack = new AudioTrack(
                AudioManager.STREAM_MUSIC, 
                44100, 
                AudioFormat.CHANNEL_OUT_STEREO, 
                AudioFormat.ENCODING_PCM_16BIT,
                8192 * 2, 
                AudioTrack.MODE_STREAM);

        extractor = new MediaExtractor();
        try 
        {
            extractor.setDataSource("http://anmp3streamingsource.com/stream");
            MediaFormat format = extractor.getTrackFormat(0);
            String mime = format.getString(MediaFormat.KEY_MIME);
            Log.d(TAG, String.format("MIME TYPE: %s", mime));

            codec = MediaCodec.createDecoderByType(mime);
            codec.configure(
                    format, 
                    null /* surface */, 
                    null /* crypto */, 
                    0 /* flags */ );
            codec.start();
            codecInputBuffers = codec.getInputBuffers();
            codecOutputBuffers = codec.getOutputBuffers();

            extractor.selectTrack(0); // <= You must select a track. You will read samples from the media from this track!

            boolean sawInputEOS = false;
            boolean sawOutputEOS = false;               

            for (;;) {
                int inputBufIndex = codec.dequeueInputBuffer(-1);
                if (inputBufIndex >= 0) {
                    ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];

                    int sampleSize = extractor.readSampleData(dstBuf, 0);
                    long presentationTimeUs = 0;
                    if (sampleSize < 0) {
                        sawInputEOS = true;
                        sampleSize = 0;
                    } else {
                        presentationTimeUs = extractor.getSampleTime();
                    }

                    codec.queueInputBuffer(inputBufIndex,
                                           0, //offset
                                           sampleSize,
                                           presentationTimeUs,
                                           sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
                    if (!sawInputEOS) {
                        extractor.advance();
                    }

                    MediaCodec.BufferInfo info = new BufferInfo();
                    final int res = codec.dequeueOutputBuffer(info, -1);
                    if (res >= 0) {
                        int outputBufIndex = res;
                        ByteBuffer buf = codecOutputBuffers[outputBufIndex];

                        final byte[] chunk = new byte[info.size];
                        buf.get(chunk); // Read the buffer all at once
                        buf.clear(); // ** MUST DO!!! OTHERWISE THE NEXT TIME YOU GET THIS SAME BUFFER BAD THINGS WILL HAPPEN

                        mAudioTrack.play();

                        if (chunk.length > 0) {
                            mAudioTrack.write(chunk, 0, chunk.length);
                        }
                        codec.releaseOutputBuffer(outputBufIndex, false /* render */);

                        if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                            sawOutputEOS = true;
                        }
                    } 
                    else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) 
                    {
                        codecOutputBuffers = codec.getOutputBuffers();
                    } 
                    else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) 
                    {
                        final MediaFormat oformat = codec.getOutputFormat();
                        Log.d(TAG, "Output format has changed to " + oformat);
                        mAudioTrack.setPlaybackRate(oformat.getInteger(MediaFormat.KEY_SAMPLE_RATE));
                    }
                 }
            }

        }                
        catch (IOException e) 
        {
            Log.e(TAG, e.getMessage());
        }
    }
}

解决方案

I haven't worked with audio, but I think I may see the problem. You're hanging in dequeueOutputBuffer() because the codec is waiting for more input.

Some of the video codecs want ~4 buffers of input before they'll even finish initialization (for example). I expect some audio codecs may behave the same way. Codec implementations vary from device to device, so it's not surprising that what runs on the emulator behaves much differently.

Change the timeouts from -1 (wait forever) to something modest (say, 1000 microseconds).