在android-NDK 10版本中使用MediaCodec进行mp3解码的第一个缓冲数据的丢失

时间:2014-10-24 09:09:18

标签: android-ndk mp3 decoding mediacodec mediaextractor

我使用来自android NDK的MediaCodec和MediaExtractor类来解码mp3文件。对于比较输入文件(mp3)和输出文件(wav - 它是我的解码格式)我看轨道持续时间,我看到持续时间50毫秒的差异。我在其他轨道上检查它,这种差异总是存在。所以,我输入的第一个接近50毫秒的输入音轨。

在androin ndk-samples(native-codec)解码片段中使用的解码算法如下

ssize_t bufidx = -1;
if (!d->sawInputEOS) 
{
    bufidx = AMediaCodec_dequeueInputBuffer(codec, 2000);
    LOGV("input buffer %zd", bufidx);
    if (bufidx >= 0) 
    {
        size_t bufsize;
        uint8_t *buf = AMediaCodec_getInputBuffer(codec, bufidx, &bufsize);
        ssize_t sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize);
        if (sampleSize < 0) 
        {
            sampleSize = 0;
            d->sawInputEOS = true;
            LOGV("EOS");
        }
        int64_t presentationTimeUs = AMediaExtractor_getSampleTime(extractor);
        AMediaCodec_queueInputBuffer(codec, bufidx, 0, sampleSize, presentationTimeUs,
d->sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
        AMediaExtractor_advance(ex);
    }
}
if (!d->sawOutputEOS) 
{
    AMediaCodecBufferInfo info;
    ssize_t status = AMediaCodec_dequeueOutputBuffer(codec, &info, 0);
    if (status >= 0) 
    {
        if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) 
        {
            LOGV("output EOS");
            d->sawOutputEOS = true;
        }

    AMediaCodec_releaseOutputBuffer(codec, status, info.size != 0);
} 
else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
LOGV("output buffers changed");
} else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
AMediaFormat *format = NULL;
format = AMediaCodec_getOutputFormat(d->codec);
LOGV("format changed to: %s", AMediaFormat_toString(format));
AMediaFormat_delete(format);
} else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
LOGV("no output buffer right now");
} else {
LOGV("unexpected info code: %zd", status);
}

}

此代码随&#34;本机编解码器提供&#34;样本在NDK。

我该如何解决?因为丢失数据是不可接受的

1 个答案:

答案 0 :(得分:0)

看起来你没有从解码器中读出缓冲的帧。当您离开解码循环时,您需要检查dequeueOutputBuffer,直到在dequeueOutputBuffer(MediaCodec.BufferInfo,long)中返回的BufferInfo上的标志BUFFER_FLAG_END_OF_STREAM

  

一旦客户端到达输入数据的末尾,它就会发出结束信号   通过指定BUFFER_FLAG_END_OF_STREAM的标志来输入流   在调用queueInputBuffer(int,int,int,long,int)时。编解码器   将继续返回输出缓冲区,直到它最终发出信号   通过指定相同的标志来结束输出流   返回的BufferInfo上的(BUFFER_FLAG_END_OF_STREAM)   dequeueOutputBuffer(MediaCodec.BufferInfo,long)。不要提交   发信号通知输入流结束后的附加输入缓冲区,   除非编解码器已被刷新,或已停止并重新启动。