OSDN Git Service

stagefright-plugins: Improvements and updates for CM14
[android-x86/external-stagefright-plugins.git] / omx / SoftFFmpegAudio.cpp
index ed0862d..7d2d855 100644 (file)
@@ -25,8 +25,8 @@
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/ACodec.h>
 #include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/OMXCodec.h>
 
 #include <OMX_AudioExt.h>
 #include <OMX_IndexExt.h>
@@ -105,7 +105,7 @@ void SoftFFmpegAudio::initPorts() {
         def.nBufferSize = 1000000; // dts!
     } else {
         // max aggregated buffer size from nuplayer
-        def.nBufferSize = 24 * 1024;
+        def.nBufferSize = 32 * 1024;
     }
 
     def.bEnabled = OMX_TRUE;
@@ -243,12 +243,13 @@ void SoftFFmpegAudio::deInitDecoder() {
 
         if (mCodecAlreadyOpened) {
             avcodec_close(mCtx);
-            av_free(mCtx);
-            mCtx = NULL;
+            mCodecAlreadyOpened = false;
         }
+        av_free(mCtx);
+        mCtx = NULL;
     }
     if (mFrame) {
-        av_freep(&mFrame);
+        av_frame_free(&mFrame);
         mFrame = NULL;
     }
     if (mSwrCtx) {
@@ -274,22 +275,31 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalGetParameter(
             profile->eEndian = OMX_EndianBig;
             profile->bInterleaved = OMX_TRUE;
             profile->ePCMMode = OMX_AUDIO_PCMModeLinear;
+                       profile->nBitPerSample = 32;
+            profile->eNumData = OMX_NumericalDataFloat;
 
             if (isConfigured()) {
-                AVSampleFormat packed = av_get_packed_sample_fmt(mAudioTgtFmt);
-                if (packed == AV_SAMPLE_FMT_U8)
-                    profile->nBitPerSample = 8;
-                else if (packed == AV_SAMPLE_FMT_S16)
-                    profile->nBitPerSample = 16;
-                else if (packed == AV_SAMPLE_FMT_S32)
-                    profile->nBitPerSample = 24;
-                else
-                    profile->nBitPerSample = av_get_bytes_per_sample(mAudioTgtFmt) * 8;
-            } else {
-                profile->nBitPerSample = 32;
+                switch (av_get_packed_sample_fmt(mAudioTgtFmt)) {
+                    case AV_SAMPLE_FMT_U8:
+                        profile->nBitPerSample = 8;
+                        profile->eNumData = OMX_NumericalDataUnsigned;
+                        break;
+                    case AV_SAMPLE_FMT_S16:
+                        profile->nBitPerSample = 16;
+                        profile->eNumData = OMX_NumericalDataSigned;
+                        break;
+                    case AV_SAMPLE_FMT_S32:
+                        profile->nBitPerSample = 32;
+                        profile->eNumData = OMX_NumericalDataSigned;
+                        break;
+                    default:
+                        profile->nBitPerSample = 32;
+                        profile->eNumData = OMX_NumericalDataFloat;
+                        break;
+                }
             }
 
-            if (getOMXChannelMapping(mAudioTgtChannels, profile->eChannelMapping) != OK) {
+            if (ACodec::getOMXChannelMapping(mAudioTgtChannels, profile->eChannelMapping) != OK) {
                 return OMX_ErrorNone;
             }
 
@@ -297,7 +307,7 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalGetParameter(
             profile->nSamplingRate = mAudioTgtFreq;
 
             //mCtx has been updated(adjustAudioParams)!
-            ALOGV("get pcm params, nChannels:%lu, nSamplingRate:%lu, nBitsPerSample:%lu",
+            ALOGV("get pcm params, nChannels:%u, nSamplingRate:%u, nBitPerSample:%u",
                    profile->nChannels, profile->nSamplingRate, profile->nBitPerSample);
 
             return OMX_ErrorNone;
@@ -418,7 +428,7 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalGetParameter(
 
             profile->nChannels = mCtx->channels;
             profile->nSampleRate = mCtx->sample_rate;
-
+            profile->nCompressionLevel = mCtx->bits_per_raw_sample;
             return OMX_ErrorNone;
         }
 
@@ -468,6 +478,23 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalGetParameter(
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioAlac:
+        {
+            OMX_AUDIO_PARAM_ALACTYPE *profile =
+                (OMX_AUDIO_PARAM_ALACTYPE *)params;
+
+            if (profile->nPortIndex != kInputPortIndex) {
+                return OMX_ErrorUndefined;
+            }
+
+            profile->nChannels = mCtx->channels;
+            profile->nSamplingRate = mCtx->sample_rate;
+
+            profile->nBitsPerSample = mCtx->bits_per_coded_sample;
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioApe:
         {
             OMX_AUDIO_PARAM_APETYPE *profile =
@@ -543,15 +570,13 @@ OMX_ERRORTYPE SoftFFmpegAudio::isRoleSupported(
 
 void SoftFFmpegAudio::adjustAudioParams() {
 
-    uint32_t max_rate = 192000;
-
     mReconfiguring = isConfigured();
 
     // let android audio mixer to downmix if there is no multichannel output
     // and use number of channels from the source file, useful for HDMI/offload output
     mAudioTgtChannels = mCtx->channels;
 
-    mAudioTgtFreq = FFMIN(max_rate, FFMAX(8000, mCtx->sample_rate));
+    mAudioTgtFreq = FFMIN(192000, FFMAX(8000, mCtx->sample_rate));
 
     mAudioTgtChannels = mCtx->channels;
     mAudioTgtFreq = mCtx->sample_rate;
@@ -582,21 +607,33 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
                 return OMX_ErrorUndefined;
             }
 
-            if (profile->nBitPerSample == 24) {
-                mAudioTgtFmt = AV_SAMPLE_FMT_S32;
-            } else if (profile->nBitPerSample == 32) {
-                mAudioTgtFmt = AV_SAMPLE_FMT_FLT;
-            } else if (profile->nBitPerSample == 8) {
-                mAudioTgtFmt = AV_SAMPLE_FMT_U8;
-            } else {
-                mAudioTgtFmt = AV_SAMPLE_FMT_S16;
+            switch (profile->nBitPerSample) {
+                case 8:
+                    mAudioTgtFmt = AV_SAMPLE_FMT_U8;
+                    break;
+                case 16:
+                    mAudioTgtFmt = AV_SAMPLE_FMT_S16;
+                    break;
+                case 24:
+                    mAudioTgtFmt = AV_SAMPLE_FMT_S32;
+                    break;
+                case 32:
+                    if (profile->eNumData == OMX_NumericalDataFloat) {
+                        mAudioTgtFmt = AV_SAMPLE_FMT_FLT;
+                        break;
+                    }
+                    mAudioTgtFmt = AV_SAMPLE_FMT_S32;
+                    break;
+                default:
+                    ALOGE("Unknown PCM encoding, assuming floating point");
+                    mAudioTgtFmt = AV_SAMPLE_FMT_FLT;
             }
 
             mAudioTgtFreq = profile->nSamplingRate;
             mAudioTgtChannels = profile->nChannels;
 
-            ALOGV("set OMX_IndexParamAudioPcm, nChannels:%lu, "
-                    "nSampleRate:%lu, nBitsPerSample:%lu",
+            ALOGV("set OMX_IndexParamAudioPcm, nChannels:%u, "
+                    "nSampleRate:%u, nBitPerSample:%u",
                 profile->nChannels, profile->nSamplingRate,
                 profile->nBitPerSample);
 
@@ -617,7 +654,7 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
 
             adjustAudioParams();
 
-            ALOGV("set OMX_IndexParamAudioAac, nChannels:%lu, nSampleRate:%lu",
+            ALOGV("set OMX_IndexParamAudioAac, nChannels:%u, nSampleRate:%u",
                 profile->nChannels, profile->nSampleRate);
 
             return OMX_ErrorNone;
@@ -637,7 +674,7 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
 
             adjustAudioParams();
 
-            ALOGV("set OMX_IndexParamAudioMp3, nChannels:%lu, nSampleRate:%lu",
+            ALOGV("set OMX_IndexParamAudioMp3, nChannels:%u, nSampleRate:%u",
                 profile->nChannels, profile->nSampleRate);
 
             return OMX_ErrorNone;
@@ -658,8 +695,8 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
             adjustAudioParams();
 
             ALOGD("set OMX_IndexParamAudioVorbis, "
-                    "nChannels=%lu, nSampleRate=%lu, nBitRate=%lu, "
-                    "nMinBitRate=%lu, nMaxBitRate=%lu",
+                    "nChannels=%u, nSampleRate=%u, nBitRate=%u, "
+                    "nMinBitRate=%u, nMaxBitRate=%u",
                 profile->nChannels, profile->nSampleRate,
                 profile->nBitRate, profile->nMinBitRate,
                 profile->nMaxBitRate);
@@ -697,7 +734,7 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
             adjustAudioParams();
 
             ALOGV("set OMX_IndexParamAudioWma, nChannels:%u, "
-                    "nSampleRate:%lu, nBitRate:%lu, nBlockAlign:%u",
+                    "nSampleRate:%u, nBitRate:%u, nBlockAlign:%u",
                 profile->nChannels, profile->nSamplingRate,
                 profile->nBitRate, profile->nBlockAlign);
 
@@ -722,8 +759,8 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
 
             adjustAudioParams();
 
-            ALOGV("set OMX_IndexParamAudioRa, nChannels:%lu, "
-                    "nSampleRate:%lu, nBlockAlign:%d",
+            ALOGV("set OMX_IndexParamAudioRa, nChannels:%u, "
+                    "nSampleRate:%u, nBlockAlign:%d",
                 profile->nChannels, profile->nSamplingRate, mCtx->block_align);
 
             return OMX_ErrorNone;
@@ -743,7 +780,7 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
 
             adjustAudioParams();
 
-            ALOGV("set OMX_IndexParamAudioFlac, nChannels:%lu, nSampleRate:%lu ",
+            ALOGV("set OMX_IndexParamAudioFlac, nChannels:%u, nSampleRate:%u ",
                 profile->nChannels, profile->nSampleRate);
 
             return OMX_ErrorNone;
@@ -763,7 +800,7 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
 
             adjustAudioParams();
 
-            ALOGV("set OMX_IndexParamAudioMp2, nChannels:%lu, nSampleRate:%lu",
+            ALOGV("set OMX_IndexParamAudioMp2, nChannels:%u, nSampleRate:%u",
                 profile->nChannels, profile->nSampleRate);
 
             return OMX_ErrorNone;
@@ -783,7 +820,7 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
 
             adjustAudioParams();
 
-            ALOGV("set OMX_IndexParamAudioAc3, nChannels:%lu, nSampleRate:%lu",
+            ALOGV("set OMX_IndexParamAudioAc3, nChannels:%u, nSampleRate:%u",
                 profile->nChannels, profile->nSamplingRate);
 
             return OMX_ErrorNone;
@@ -803,12 +840,34 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
 
             adjustAudioParams();
 
-            ALOGV("set OMX_IndexParamAudioAndroidAc3, nChannels:%lu, nSampleRate:%lu",
+            ALOGV("set OMX_IndexParamAudioAndroidAc3, nChannels:%u, nSampleRate:%u",
                 profile->nChannels, profile->nSampleRate);
 
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioAlac:
+        {
+            OMX_AUDIO_PARAM_ALACTYPE *profile =
+                (OMX_AUDIO_PARAM_ALACTYPE *)params;
+
+            if (profile->nPortIndex != kInputPortIndex) {
+                return OMX_ErrorUndefined;
+            }
+
+            mCtx->channels = profile->nChannels;
+            mCtx->sample_rate = profile->nSamplingRate;
+            mCtx->bits_per_coded_sample = profile->nBitsPerSample;
+
+            adjustAudioParams();
+
+            ALOGV("set OMX_IndexParamAudioAlac, nChannels:%u, "
+                    "nSampleRate:%u, nBitsPerSample:%u",
+                profile->nChannels, profile->nSamplingRate,
+                profile->nBitsPerSample);
+
+            return OMX_ErrorNone;
+        }
 
         case OMX_IndexParamAudioApe:
         {
@@ -825,8 +884,8 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
 
             adjustAudioParams();
 
-            ALOGV("set OMX_IndexParamAudioApe, nChannels:%lu, "
-                    "nSampleRate:%lu, nBitsPerSample:%lu",
+            ALOGV("set OMX_IndexParamAudioApe, nChannels:%u, "
+                    "nSampleRate:%u, nBitsPerSample:%u",
                 profile->nChannels, profile->nSamplingRate,
                 profile->nBitsPerSample);
 
@@ -847,7 +906,7 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
 
             adjustAudioParams();
 
-            ALOGV("set OMX_IndexParamAudioDts, nChannels:%lu, nSampleRate:%lu",
+            ALOGV("set OMX_IndexParamAudioDts, nChannels:%u, nSampleRate:%u",
                 profile->nChannels, profile->nSamplingRate);
 
             return OMX_ErrorNone;
@@ -873,9 +932,9 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
             adjustAudioParams();
 
             ALOGD("set OMX_IndexParamAudioFFmpeg, "
-                "eCodecId:%ld(%s), nChannels:%lu, nBitRate:%lu, "
-                "nBitsPerSample:%lu, nSampleRate:%lu, "
-                "nBlockAlign:%lu, eSampleFormat:%lu(%s)",
+                "eCodecId:%d(%s), nChannels:%u, nBitRate:%u, "
+                "nBitsPerSample:%u, nSampleRate:%u, "
+                "nBlockAlign:%u, eSampleFormat:%u(%s)",
                 profile->eCodecId, avcodec_get_name(mCtx->codec_id),
                 profile->nChannels, profile->nBitRate,
                 profile->nBitsPerSample, profile->nSampleRate,
@@ -923,12 +982,12 @@ int32_t SoftFFmpegAudio::handleExtradata() {
     BufferInfo *inInfo = *inQueue.begin();
     OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
 
-    ALOGI("got extradata, ignore: %d, size: %lu",
+    ALOGI("got extradata, ignore: %d, size: %u",
             mIgnoreExtradata, inHeader->nFilledLen);
     hexdump(inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen);
 
     if (mIgnoreExtradata) {
-        ALOGI("got extradata, size: %lu, but ignore it", inHeader->nFilledLen);
+        ALOGI("got extradata, size: %u, but ignore it", inHeader->nFilledLen);
     } else {
         if (!mExtradataReady) {
             uint32_t ret = ERR_OK;
@@ -1068,29 +1127,37 @@ int32_t SoftFFmpegAudio::decodeAudio() {
     int gotFrm = false;
     int32_t ret = ERR_OK;
     int32_t inputBufferUsedLength = 0;
-    bool is_flush = (mEOSStatus != INPUT_DATA_AVAILABLE);
+    bool is_flush = (mEOSStatus == OUTPUT_FRAMES_FLUSHED);
     List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
     BufferInfo *inInfo = NULL;
     OMX_BUFFERHEADERTYPE *inHeader = NULL;
 
     CHECK_EQ(mResampledDataSize, 0);
 
-    if (!is_flush) {
+    if (!is_flush && !inQueue.empty()) {
         inInfo = *inQueue.begin();
-        CHECK(inInfo != NULL);
-        inHeader = inInfo->mHeader;
+        if (inInfo != NULL)  {
+            inHeader = inInfo->mHeader;
 
-        if (mInputBufferSize == 0) {
-            updateTimeStamp(inHeader);
-            mInputBufferSize = inHeader->nFilledLen;
+            if (mInputBufferSize == 0) {
+                updateTimeStamp(inHeader);
+                mInputBufferSize = inHeader->nFilledLen;
+            }
         }
     }
 
+    if (mEOSStatus == INPUT_EOS_SEEN && (!inHeader || inHeader->nFilledLen == 0)
+        && !(mCtx->codec->capabilities & CODEC_CAP_DELAY)) {
+        return ERR_FLUSHED;
+    }
+
     AVPacket pkt;
     initPacket(&pkt, inHeader);
     av_frame_unref(mFrame);
 
     len = avcodec_decode_audio4(mCtx, mFrame, &gotFrm, &pkt);
+    av_packet_unref(&pkt);
+
     //a negative error code is returned if an error occurred during decoding
     if (len < 0) {
         ALOGW("ffmpeg audio decoder err, we skip the frame and play silence instead");
@@ -1124,17 +1191,19 @@ int32_t SoftFFmpegAudio::decodeAudio() {
         } else {
             inputBufferUsedLength = len;
         }
-
-        CHECK_GE(inHeader->nFilledLen, inputBufferUsedLength);
-        inHeader->nOffset += inputBufferUsedLength;
-        inHeader->nFilledLen -= inputBufferUsedLength;
         mInputBufferSize -= inputBufferUsedLength;
 
-        if (inHeader->nFilledLen == 0) {
-            CHECK_EQ(mInputBufferSize, 0);
-            inQueue.erase(inQueue.begin());
-            inInfo->mOwnedByUs = false;
-            notifyEmptyBufferDone(inHeader);
+        if (inHeader != NULL) {
+            CHECK_GE(inHeader->nFilledLen, inputBufferUsedLength);
+            inHeader->nOffset += inputBufferUsedLength;
+            inHeader->nFilledLen -= inputBufferUsedLength;
+
+            if (inHeader->nFilledLen == 0) {
+                CHECK_EQ(mInputBufferSize, 0);
+                inQueue.erase(inQueue.begin());
+                inInfo->mOwnedByUs = false;
+                notifyEmptyBufferDone(inHeader);
+            }
         }
     }
 
@@ -1332,12 +1401,6 @@ void SoftFFmpegAudio::drainAllOutputBuffers() {
         return;
     }
 
-    if(!(mCtx->codec->capabilities & CODEC_CAP_DELAY)) {
-        drainEOSOutputBuffer();
-        mEOSStatus = OUTPUT_FRAMES_FLUSHED;
-        return;
-    }
-
     while (!outQueue.empty()) {
         if (mResampledDataSize == 0) {
             int32_t err = decodeAudio();
@@ -1386,10 +1449,7 @@ void SoftFFmpegAudio::onQueueFilled(OMX_U32 /* portIndex */) {
         inHeader = inInfo->mHeader;
 
         if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
-            ALOGD("ffmpeg audio decoder empty eos inbuf");
-            inQueue.erase(inQueue.begin());
-            inInfo->mOwnedByUs = false;
-            notifyEmptyBufferDone(inHeader);
+            ALOGD("ffmpeg audio decoder eos");
             mEOSStatus = INPUT_EOS_SEEN;
             continue;
         }
@@ -1432,9 +1492,9 @@ void SoftFFmpegAudio::onQueueFilled(OMX_U32 /* portIndex */) {
 }
 
 void SoftFFmpegAudio::onPortFlushCompleted(OMX_U32 portIndex) {
-    ALOGV("ffmpeg audio decoder flush port(%lu)", portIndex);
+    ALOGV("ffmpeg audio decoder flush port(%u)", portIndex);
     if (portIndex == kInputPortIndex) {
-        if (mCtx && mCtx->codec) {
+        if (mCtx && avcodec_is_open(mCtx)) {
             //Make sure that the next buffer output does not still
             //depend on fragments from the last one decoded.
             avcodec_flush_buffers(mCtx);
@@ -1479,7 +1539,7 @@ int64_t SoftFFmpegAudio::getAudioClock() {
         sAudioClock = (int64_t*) malloc(sizeof(int64_t));
         *sAudioClock = 0;
     }
-    ALOGV("getAudioClock: %lld", *sAudioClock);
+    ALOGV("getAudioClock: %" PRId64, *sAudioClock);
     return *sAudioClock;
 }
 
@@ -1496,6 +1556,7 @@ void SoftFFmpegAudio::onReset() {
     initDecoder(codecID);
     mSignalledError = false;
     mOutputPortSettingsChange = NONE;
+    mEOSStatus = INPUT_DATA_AVAILABLE;
 }
 
 SoftOMXComponent* SoftFFmpegAudio::createSoftOMXComponent(