OSDN Git Service

Merge branch 'lollipop-x86' into multiwindow-hwaccel
[android-x86/external-stagefright-plugins.git] / omx / SoftFFmpegAudio.cpp
index b43fd81..43ac9d9 100644 (file)
@@ -15,7 +15,6 @@
  * limitations under the License.
  */
 
-//#define LOG_NDEBUG 0
 #define LOG_TAG "SoftFFmpegAudio"
 #include <utils/Log.h>
 #include <cutils/properties.h>
 
 #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>
 
 #define DEBUG_PKT 0
 #define DEBUG_FRM 0
+#define DEBUG_EXTRADATA 0
 
 namespace android {
 
 template<class T>
 static void InitOMXParams(T *params) {
+    memset(params, 0, sizeof(T));
     params->nSize = sizeof(T);
     params->nVersion.s.nVersionMajor = 1;
     params->nVersion.s.nVersionMinor = 0;
@@ -144,24 +145,19 @@ void SoftFFmpegAudio::setDefaultCtx(AVCodecContext *avctx, const AVCodec *codec)
     int fast = 0;
 
     avctx->workaround_bugs   = 1;
-    avctx->lowres            = 0;
-    if(avctx->lowres > codec->max_lowres){
-        ALOGW("The maximum value for lowres supported by the decoder is %d",
-                codec->max_lowres);
-        avctx->lowres= codec->max_lowres;
-    }
     avctx->idct_algo         = 0;
     avctx->skip_frame        = AVDISCARD_DEFAULT;
     avctx->skip_idct         = AVDISCARD_DEFAULT;
     avctx->skip_loop_filter  = AVDISCARD_DEFAULT;
     avctx->error_concealment = 3;
 
-    avctx->flags |= CODEC_FLAG_BITEXACT;
+    avctx->flags |= AV_CODEC_FLAG_BITEXACT;
 
-    if(avctx->lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
-    if (fast)   avctx->flags2 |= CODEC_FLAG2_FAST;
-    if(codec->capabilities & CODEC_CAP_DR1)
+    if (fast) avctx->flags2 |= AV_CODEC_FLAG2_FAST;
+#ifdef CODEC_FLAG_EMU_EDGE
+    if (codec->capabilities & AV_CODEC_CAP_DR1)
         avctx->flags |= CODEC_FLAG_EMU_EDGE;
+#endif
 }
 
 bool SoftFFmpegAudio::isConfigured() {
@@ -249,13 +245,16 @@ void SoftFFmpegAudio::deInitDecoder() {
         mCtx = NULL;
     }
     if (mFrame) {
-        av_freep(&mFrame);
+        av_frame_free(&mFrame);
         mFrame = NULL;
     }
+#ifdef LIBAV_CONFIG_H
+#else
     if (mSwrCtx) {
         swr_free(&mSwrCtx);
         mSwrCtx = NULL;
     }
+#endif
 }
 
 OMX_ERRORTYPE SoftFFmpegAudio::internalGetParameter(
@@ -275,22 +274,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;
             }
 
@@ -298,7 +306,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;
@@ -419,7 +427,7 @@ OMX_ERRORTYPE SoftFFmpegAudio::internalGetParameter(
 
             profile->nChannels = mCtx->channels;
             profile->nSampleRate = mCtx->sample_rate;
-
+            profile->nCompressionLevel = mCtx->bits_per_raw_sample;
             return OMX_ErrorNone;
         }
 
@@ -469,6 +477,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 =
@@ -581,21 +606,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);
 
@@ -808,6 +845,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:
         {
@@ -922,9 +981,11 @@ int32_t SoftFFmpegAudio::handleExtradata() {
     BufferInfo *inInfo = *inQueue.begin();
     OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
 
+#if DEBUG_EXTRADATA
     ALOGI("got extradata, ignore: %d, size: %u",
             mIgnoreExtradata, inHeader->nFilledLen);
     hexdump(inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen);
+#endif
 
     if (mIgnoreExtradata) {
         ALOGI("got extradata, size: %u, but ignore it", inHeader->nFilledLen);
@@ -940,7 +1001,7 @@ int32_t SoftFFmpegAudio::handleExtradata() {
                 int orig_extradata_size = mCtx->extradata_size;
                 mCtx->extradata_size += inHeader->nFilledLen;
                 mCtx->extradata = (uint8_t *)av_realloc(mCtx->extradata,
-                    mCtx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+                    mCtx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
                 if (!mCtx->extradata) {
                     ALOGE("ffmpeg audio decoder failed to alloc extradata memory.");
                     return ERR_OOM;
@@ -948,7 +1009,7 @@ int32_t SoftFFmpegAudio::handleExtradata() {
 
                 memcpy(mCtx->extradata + orig_extradata_size,
                     inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen);
-                memset(mCtx->extradata + mCtx->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+                memset(mCtx->extradata + mCtx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
             }
         }
     }
@@ -977,8 +1038,10 @@ int32_t SoftFFmpegAudio::openDecoder() {
             }
             deinitVorbisHdr();
         }
+#if DEBUG_EXTRADATA
         ALOGI("extradata is ready, size: %d", mCtx->extradata_size);
         hexdump(mCtx->extradata, mCtx->extradata_size);
+#endif
         mExtradataReady = true;
     }
 
@@ -1087,15 +1150,16 @@ int32_t SoftFFmpegAudio::decodeAudio() {
     }
 
     if (mEOSStatus == INPUT_EOS_SEEN && (!inHeader || inHeader->nFilledLen == 0)
-        && !(mCtx->codec->capabilities & CODEC_CAP_DELAY)) {
+        && !(mCtx->codec->capabilities & AV_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");
@@ -1111,7 +1175,7 @@ int32_t SoftFFmpegAudio::decodeAudio() {
             ALOGI("ffmpeg audio decoder failed to get frame.");
 #endif
             //stop sending empty packets if the decoder is finished
-            if (is_flush && mCtx->codec->capabilities & CODEC_CAP_DELAY) {
+            if (is_flush && mCtx->codec->capabilities & AV_CODEC_CAP_DELAY) {
                 ALOGI("ffmpeg audio decoder failed to get more frames when flush.");
                 ret = ERR_FLUSHED;
             } else {
@@ -1129,23 +1193,29 @@ 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);
+            }
         }
     }
 
     return ret;
 }
 
+#ifdef LIBAV_CONFIG_H
+#define av_frame_get_channels(f) av_get_channel_layout_nb_channels(f->channel_layout)
+#endif
+
 int32_t SoftFFmpegAudio::resampleAudio() {
     int channels = 0;
     int64_t channelLayout = 0;
@@ -1173,6 +1243,9 @@ int32_t SoftFFmpegAudio::resampleAudio() {
                 || mAudioSrcFmt != mAudioTgtFmt
                 || mAudioSrcChannelLayout != mAudioTgtChannelLayout
                 || mAudioSrcFreq != mAudioTgtFreq))) {
+#ifdef LIBAV_CONFIG_H
+        if (!mSwrCtx) {
+#else
         if (mSwrCtx) {
             swr_free(&mSwrCtx);
         }
@@ -1181,6 +1254,7 @@ int32_t SoftFFmpegAudio::resampleAudio() {
                 channelLayout,       (enum AVSampleFormat)mFrame->format, mFrame->sample_rate,
                 0, NULL);
         if (!mSwrCtx || swr_init(mSwrCtx) < 0) {
+#endif
             ALOGE("Cannot create sample rate converter for conversion "
                     "of %d Hz %s %d channels to %d Hz %s %d channels!",
                     mFrame->sample_rate,
@@ -1218,6 +1292,8 @@ int32_t SoftFFmpegAudio::resampleAudio() {
     }
 
     if (mSwrCtx) {
+#ifdef LIBAV_CONFIG_H
+#else
         const uint8_t **in = (const uint8_t **)mFrame->extended_data;
         uint8_t *out[] = {mAudioBuffer};
         int out_count = sizeof(mAudioBuffer) / mAudioTgtChannels / av_get_bytes_per_sample(mAudioTgtFmt);
@@ -1249,6 +1325,7 @@ int32_t SoftFFmpegAudio::resampleAudio() {
                 mAudioTgtChannels,
                 av_get_sample_fmt_name(mAudioTgtFmt));
 #endif
+#endif
     } else {
         mResampledData = mFrame->data[0];
         mResampledDataSize = dataSize;
@@ -1475,7 +1552,7 @@ int64_t SoftFFmpegAudio::getAudioClock() {
         sAudioClock = (int64_t*) malloc(sizeof(int64_t));
         *sAudioClock = 0;
     }
-    ALOGV("getAudioClock: %lld", *sAudioClock);
+    ALOGV("getAudioClock: %" PRId64, *sAudioClock);
     return *sAudioClock;
 }