简体   繁体   English

Android MediaCodec API-音乐在模拟器上播放,不在设备上播放

[英]Android MediaCodec API - Music Plays on Emulator, Not on the Device

The code given below works fine on the emulator, but not the device. 下面给出的代码在模拟器上可以正常运行,但在设备上不能正常运行。 I found the following lines that looked suspicious to me: 我发现以下几行对我来说可疑:

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 V / MediaExtractor(5030):自动检测为“音频/ mpeg”的媒体内容,置信度为0.20 V / ChromiumHTTPDataSource(5030):mContentSize未定义或网络可能已断开V / ChromiumHTTPDataSource(5030):mContentSize未定义或网络可能已断开D /com.example.mediacodectest(5030):MIME类型:音频/ 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. 由于编码解码器正在等待更多输入,因此您陷入了dequeueOutputBuffer()

Some of the video codecs want ~4 buffers of input before they'll even finish initialization ( for example ). 一些视频编解码器在完成初始化之前需要大约4个输入缓冲区( 例如 )。 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). 将超时从-1(永远等待)更改为适度(例如1000微秒)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM