OSDN Git Service

stagefright-plugins: Fix HEVC extradata handling
[android-x86/external-stagefright-plugins.git] / extractor / FFmpegExtractor.cpp
index 89b5d5a..38b0a33 100644 (file)
@@ -94,6 +94,7 @@ private:
     mutable Mutex mLock;
 
     bool mIsAVC;
+    bool mIsHEVC;
     size_t mNALLengthSize;
     bool mNal2AnnexB;
 
@@ -586,6 +587,9 @@ int FFmpegExtractor::stream_component_open(int stream_index)
     if (!supported) {
         ALOGE("unsupport the codec(%s)", avcodec_get_name(avctx->codec_id));
         return -1;
+    } else if (mFormatCtx->streams[stream_index]->disposition & AV_DISPOSITION_ATTACHED_PIC) {
+        ALOGD("not opening attached picture(%s)", avcodec_get_name(avctx->codec_id));
+        return -1;
     }
     ALOGI("support the codec(%s)", avcodec_get_name(avctx->codec_id));
 
@@ -897,6 +901,7 @@ int FFmpegExtractor::initStreams()
     st_index[AVMEDIA_TYPE_VIDEO]  = -1;
     wanted_stream[AVMEDIA_TYPE_AUDIO]  = -1;
     wanted_stream[AVMEDIA_TYPE_VIDEO]  = -1;
+    AVDictionary *format_opts = NULL, *codec_opts = NULL;
     const char *mime = NULL;
 
     setFFmpegDefaultOpts();
@@ -929,9 +934,12 @@ int FFmpegExtractor::initStreams()
         ALOGE("Option %s not found.\n", t->key);
         //ret = AVERROR_OPTION_NOT_FOUND;
         ret = -1;
+        av_dict_free(&format_opts);
         goto fail;
     }
 
+    av_dict_free(&format_opts);
+
     if (mGenPTS)
         mFormatCtx->flags |= AVFMT_FLAG_GENPTS;
 
@@ -1144,15 +1152,15 @@ void FFmpegExtractor::readerEntry() {
             ret = avformat_seek_file(mFormatCtx, -1, mSeekMin, mSeekPos, mSeekMax, 0);
             if (ret < 0) {
                 ALOGE("%s: error while seeking", mFormatCtx->filename);
-            } else {
-                if (mAudioStreamIdx >= 0) {
-                    packet_queue_flush(&mAudioQ);
-                    packet_queue_put(&mAudioQ, &mAudioQ.flush_pkt);
-                }
-                if (mVideoStreamIdx >= 0) {
-                    packet_queue_flush(&mVideoQ);
-                    packet_queue_put(&mVideoQ, &mVideoQ.flush_pkt);
-                }
+                avformat_seek_file(mFormatCtx, -1, 0, 0, 0, 0);
+            }
+            if (mAudioStreamIdx >= 0) {
+                packet_queue_flush(&mAudioQ);
+                packet_queue_put(&mAudioQ, &mAudioQ.flush_pkt);
+            }
+            if (mVideoStreamIdx >= 0) {
+                packet_queue_flush(&mVideoQ);
+                packet_queue_put(&mVideoQ, &mVideoQ.flush_pkt);
             }
             mSeekIdx = -1;
             eof = false;
@@ -1290,6 +1298,7 @@ FFmpegSource::FFmpegSource(
     : mExtractor(extractor),
       mTrackIndex(index),
       mIsAVC(false),
+      mIsHEVC(false),
       mNal2AnnexB(false),
       mStream(mExtractor->mTracks.itemAt(index).mStream),
       mQueue(mExtractor->mTracks.itemAt(index).mQueue),
@@ -1322,6 +1331,26 @@ FFmpegSource::FFmpegSource(
             ALOGV("the stream is AVC, the length of a NAL unit: %d", mNALLengthSize);
 
             mNal2AnnexB = true;
+        } else if (avctx->codec_id == AV_CODEC_ID_HEVC
+                && avctx->extradata_size > 0) {
+            mIsHEVC = true;
+
+            uint32_t type;
+            const void *data;
+            size_t size;
+            CHECK(meta->findData(kKeyHVCC, &type, &data, &size));
+
+            const uint8_t *ptr = (const uint8_t *)data;
+
+            CHECK(size >= 7);
+            //CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
+
+            // The number of bytes used to encode the length of a NAL unit.
+            mNALLengthSize = 1 + (ptr[21] & 3);
+
+            ALOGD("the stream is HEVC, the length of a NAL unit: %d", mNALLengthSize);
+
+            mNal2AnnexB = true;
         }
     }
 
@@ -1434,7 +1463,7 @@ retry:
     mediaBuffer->set_range(0, pkt.size);
 
     //copy data
-    if (mIsAVC && mNal2AnnexB) {
+    if ((mIsAVC || mIsHEVC) && mNal2AnnexB) {
         /* This only works for NAL sizes 3-4 */
         CHECK(mNALLengthSize == 3 || mNALLengthSize == 4);
 
@@ -1601,7 +1630,6 @@ static bool isCodecSupportedByStagefright(enum AVCodecID codec_id)
     case AV_CODEC_ID_MP3:
     case AV_CODEC_ID_AMR_NB:
     case AV_CODEC_ID_AMR_WB:
-    case AV_CODEC_ID_FLAC:
     case AV_CODEC_ID_VORBIS:
     case AV_CODEC_ID_PCM_MULAW: //g711
     case AV_CODEC_ID_PCM_ALAW:  //g711
@@ -1881,6 +1909,7 @@ static const char *SniffFFMPEGCommon(const char *url, float *confidence, bool fa
     size_t nb_streams = 0;
     const char *container = NULL;
     AVFormatContext *ic = NULL;
+    AVDictionary *codec_opts = NULL;
     AVDictionary **opts = NULL;
 
     status_t status = initFFmpeg();