OSDN Git Service

stagefright-plugins: Improvements and updates for CM14
[android-x86/external-stagefright-plugins.git] / omx / SoftFFmpegAudio.cpp
index 4315496..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>
@@ -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:%u, nSamplingRate:%u, nBitsPerSample:%u",
+            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 =
@@ -580,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:%u, "
-                    "nSampleRate:%u, nBitsPerSample:%u",
+                    "nSampleRate:%u, nBitPerSample:%u",
                 profile->nChannels, profile->nSamplingRate,
                 profile->nBitPerSample);
 
@@ -807,6 +846,28 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalSetParameter(
             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:
         {
@@ -1066,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");
@@ -1122,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);
+            }
         }
     }
 
@@ -1330,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();
@@ -1384,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,7 +1494,7 @@ void SoftFFmpegAudio::onQueueFilled(OMX_U32 /* portIndex */) {
 void SoftFFmpegAudio::onPortFlushCompleted(OMX_U32 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);
@@ -1477,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;
 }
 
@@ -1494,6 +1556,7 @@ void SoftFFmpegAudio::onReset() {
     initDecoder(codecID);
     mSignalledError = false;
     mOutputPortSettingsChange = NONE;
+    mEOSStatus = INPUT_DATA_AVAILABLE;
 }
 
 SoftOMXComponent* SoftFFmpegAudio::createSoftOMXComponent(