OSDN Git Service

add HEVC(H.265) decoder. plz sync:
[android-x86/external-stagefright-plugins.git] / libstagefright / FFmpegExtractor / FFmpegExtractor.cpp
index 28cbeed..08fa7a2 100644 (file)
@@ -375,7 +375,7 @@ static uint32_t get_sample_rate(const uint8_t sf_index)
 
 int FFmpegExtractor::check_extradata(AVCodecContext *avctx)
 {
-    enum AVCodecID codec_id = CODEC_ID_NONE;
+    enum AVCodecID codec_id = AV_CODEC_ID_NONE;
     const char *name = NULL;
     bool *defersToCreateTrack = NULL;
     AVBitStreamFilterContext **bsfc = NULL;
@@ -392,16 +392,16 @@ int FFmpegExtractor::check_extradata(AVCodecContext *avctx)
        codec_id = avctx->codec_id;
 
     // ignore extradata
-    if (codec_id != CODEC_ID_H264
-            && codec_id != CODEC_ID_MPEG4
-            && codec_id != CODEC_ID_MPEG1VIDEO
-            && codec_id != CODEC_ID_MPEG2VIDEO
-            && codec_id != CODEC_ID_AAC) {
+    if (codec_id != AV_CODEC_ID_H264
+            && codec_id != AV_CODEC_ID_MPEG4
+            && codec_id != AV_CODEC_ID_MPEG1VIDEO
+            && codec_id != AV_CODEC_ID_MPEG2VIDEO
+            && codec_id != AV_CODEC_ID_AAC) {
         return 1;
     }
 
     // is extradata compatible with android?
-    if (codec_id != CODEC_ID_AAC) {
+    if (codec_id != AV_CODEC_ID_AAC) {
         int is_compatible = is_extradata_compatible_with_android(avctx);
         if (!is_compatible) {
             ALOGI("%s extradata is not compatible with android, should to extract it from bitstream",
@@ -413,7 +413,7 @@ int FFmpegExtractor::check_extradata(AVCodecContext *avctx)
         return 1;
     }
 
-    if (codec_id == CODEC_ID_AAC) {
+    if (codec_id == AV_CODEC_ID_AAC) {
         name = "aac_adtstoasc";
     }
 
@@ -461,38 +461,41 @@ bool FFmpegExtractor::is_codec_supported(enum AVCodecID codec_id)
     bool supported = false;
 
     switch(codec_id) {
-    case CODEC_ID_H264:
-    case CODEC_ID_MPEG4:
-    case CODEC_ID_H263:
-    case CODEC_ID_H263P:
-    case CODEC_ID_H263I:
-    case CODEC_ID_AAC:
-    case CODEC_ID_AC3:
-    case CODEC_ID_MP1:
-    case CODEC_ID_MP2:
-    case CODEC_ID_MP3:
-    case CODEC_ID_MPEG1VIDEO:
-    case CODEC_ID_MPEG2VIDEO:
-    case CODEC_ID_WMV1:
-    case CODEC_ID_WMV2:
-    case CODEC_ID_WMV3:
-    case CODEC_ID_VC1:
-    case CODEC_ID_WMAV1:
-    case CODEC_ID_WMAV2:
-    case CODEC_ID_WMAPRO:
-    case CODEC_ID_WMALOSSLESS:
-    case CODEC_ID_RV20:
-    case CODEC_ID_RV30:
-    case CODEC_ID_RV40:
-    case CODEC_ID_COOK:
-    case CODEC_ID_APE:
-    case CODEC_ID_DTS:
-    case CODEC_ID_FLAC:
-    case CODEC_ID_FLV1:
+    case AV_CODEC_ID_H264:
+    case AV_CODEC_ID_MPEG4:
+    case AV_CODEC_ID_H263:
+    case AV_CODEC_ID_H263P:
+    case AV_CODEC_ID_H263I:
+    case AV_CODEC_ID_AAC:
+    case AV_CODEC_ID_AC3:
+    case AV_CODEC_ID_MP2:
+    case AV_CODEC_ID_MP3:
+    case AV_CODEC_ID_MPEG1VIDEO:
+    case AV_CODEC_ID_MPEG2VIDEO:
+    case AV_CODEC_ID_WMV1:
+    case AV_CODEC_ID_WMV2:
+    case AV_CODEC_ID_WMV3:
+    case AV_CODEC_ID_VC1:
+    case AV_CODEC_ID_WMAV1:
+    case AV_CODEC_ID_WMAV2:
+    case AV_CODEC_ID_WMAPRO:
+    case AV_CODEC_ID_WMALOSSLESS:
+    case AV_CODEC_ID_RV20:
+    case AV_CODEC_ID_RV30:
+    case AV_CODEC_ID_RV40:
+    case AV_CODEC_ID_COOK:
+    case AV_CODEC_ID_APE:
+    case AV_CODEC_ID_DTS:
+    case AV_CODEC_ID_FLAC:
+    case AV_CODEC_ID_FLV1:
+    case AV_CODEC_ID_VORBIS:
+    case AV_CODEC_ID_HEVC:
+
         supported = true;
         break;
     default:
-        ALOGD("unsuppoted codec(id:0x%0x), but give it a chance", codec_id);
+        ALOGD("unsuppoted codec(%s), but give it a chance",
+                avcodec_get_name(codec_id));
         //Won't promise that the following codec id can be supported.
            //Just give these codecs a chance.
         supported = true;
@@ -521,10 +524,10 @@ int FFmpegExtractor::stream_component_open(int stream_index)
     supported = is_codec_supported(avctx->codec_id);
 
     if (!supported) {
-        ALOGE("unsupport the codec, id: 0x%0x", avctx->codec_id);
+        ALOGE("unsupport the codec(%s)", avcodec_get_name(avctx->codec_id));
         return -1;
     }
-    ALOGV("support the codec");
+    ALOGI("support the codec(%s)", avcodec_get_name(avctx->codec_id));
 
     unsigned streamType;
     ssize_t index = mTracks.indexOfKey(stream_index);
@@ -538,7 +541,7 @@ int FFmpegExtractor::stream_component_open(int stream_index)
 
     char tagbuf[32];
     av_get_codec_tag_string(tagbuf, sizeof(tagbuf), avctx->codec_tag);
-    ALOGV("Tag %s/0x%08x with codec id '%d'\n", tagbuf, avctx->codec_tag, avctx->codec_id);
+    ALOGV("Tag %s/0x%08x with codec(%s)\n", tagbuf, avctx->codec_tag, avcodec_get_name(avctx->codec_id));
 
     switch (avctx->codec_type) {
     case AVMEDIA_TYPE_VIDEO:
@@ -574,7 +577,7 @@ int FFmpegExtractor::stream_component_open(int stream_index)
         meta = new MetaData;
 
         switch(avctx->codec_id) {
-        case CODEC_ID_H264:
+        case AV_CODEC_ID_H264:
             /**
              * H.264 Video Types
              * http://msdn.microsoft.com/en-us/library/dd757808(v=vs.85).aspx
@@ -610,7 +613,7 @@ int FFmpegExtractor::stream_component_open(int stream_index)
                 meta = MakeAVCCodecSpecificData(buffer);
             }
             break;
-        case CODEC_ID_MPEG4:
+        case AV_CODEC_ID_MPEG4:
             ALOGV("MPEG4");
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
             {
@@ -620,15 +623,15 @@ int FFmpegExtractor::stream_component_open(int stream_index)
                 meta->setData(kKeyESDS, kTypeESDS, esds->data(), esds->size());
             }
             break;
-        case CODEC_ID_H263:
-        case CODEC_ID_H263P:
-        case CODEC_ID_H263I:
+        case AV_CODEC_ID_H263:
+        case AV_CODEC_ID_H263P:
+        case AV_CODEC_ID_H263I:
             ALOGV("H263");
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
             break;
-        case CODEC_ID_MPEG1VIDEO:
-        case CODEC_ID_MPEG2VIDEO:
-            ALOGV("MPEG%dVIDEO", avctx->codec_id == CODEC_ID_MPEG2VIDEO ? 2 : 1);
+        case AV_CODEC_ID_MPEG1VIDEO:
+        case AV_CODEC_ID_MPEG2VIDEO:
+            ALOGV("MPEG%dVIDEO", avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ? 2 : 1);
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG2);
             {
                 sp<ABuffer> csd = new ABuffer(avctx->extradata_size);
@@ -637,50 +640,55 @@ int FFmpegExtractor::stream_component_open(int stream_index)
                 meta->setData(kKeyESDS, kTypeESDS, esds->data(), esds->size());
             }
             break;
-        case CODEC_ID_VC1:
+        case AV_CODEC_ID_VC1:
             ALOGV("VC1");
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VC1);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             break;
-        case CODEC_ID_WMV1:
+        case AV_CODEC_ID_WMV1:
             ALOGV("WMV1");
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_WMV);
             meta->setInt32(kKeyWMVVersion, kTypeWMVVer_7);
             break;
-        case CODEC_ID_WMV2:
+        case AV_CODEC_ID_WMV2:
             ALOGV("WMV2");
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_WMV);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             meta->setInt32(kKeyWMVVersion, kTypeWMVVer_8);
             break;
-        case CODEC_ID_WMV3:
+        case AV_CODEC_ID_WMV3:
             ALOGV("WMV3");
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_WMV);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             meta->setInt32(kKeyWMVVersion, kTypeWMVVer_9);
             break;
-        case CODEC_ID_RV20:
+        case AV_CODEC_ID_RV20:
             ALOGV("RV30");
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RV);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             meta->setInt32(kKeyRVVersion, kTypeRVVer_G2); //http://en.wikipedia.org/wiki/RealVideo
-        case CODEC_ID_RV30:
+        case AV_CODEC_ID_RV30:
             ALOGV("RV30");
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RV);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             meta->setInt32(kKeyRVVersion, kTypeRVVer_8); //http://en.wikipedia.org/wiki/RealVideo
             break;
-        case CODEC_ID_RV40:
+        case AV_CODEC_ID_RV40:
             ALOGV("RV40");
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RV);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             meta->setInt32(kKeyRVVersion, kTypeRVVer_9); //http://en.wikipedia.org/wiki/RealVideo
             break;
-        case CODEC_ID_FLV1:
+        case AV_CODEC_ID_FLV1:
             ALOGV("FLV1");
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_FLV1);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             break;
+        case AV_CODEC_ID_HEVC:
+            ALOGV("HEVC");
+            meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
+            meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+            break;
         default:
             ALOGD("unsuppoted video codec(id:%d, name:%s), but give it a chance",
                     avctx->codec_id, avcodec_get_name(avctx->codec_id));
@@ -747,34 +755,35 @@ int FFmpegExtractor::stream_component_open(int stream_index)
         }
 
         if (avctx->extradata) {
-            ALOGV("audio stream extradata:");
+            ALOGV("audio stream extradata(%d):", avctx->extradata_size);
             hexdump(avctx->extradata, avctx->extradata_size);
         } else {
             ALOGV("audio stream no extradata, but we can ignore it.");
         }
 
         switch(avctx->codec_id) {
-        case CODEC_ID_MP1:
-            ALOGV("MP1");
-            meta = new MetaData;
-            meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I);
-            break;
-        case CODEC_ID_MP2:
+        case AV_CODEC_ID_MP2:
             ALOGV("MP2");
             meta = new MetaData;
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
             break;
-        case CODEC_ID_MP3:
+        case AV_CODEC_ID_MP3:
             ALOGV("MP3");
             meta = new MetaData;
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
             break;
-        case CODEC_ID_AC3:
+        case AV_CODEC_ID_VORBIS:
+            ALOGV("VORBIS");
+            meta = new MetaData;
+            meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
+            meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+            break;
+        case AV_CODEC_ID_AC3:
             ALOGV("AC3");
             meta = new MetaData;
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3);
             break;
-        case CODEC_ID_AAC:
+        case AV_CODEC_ID_AAC:
             ALOGV("AAC");
             uint32_t sr;
             const uint8_t *header;
@@ -801,52 +810,52 @@ int FFmpegExtractor::stream_component_open(int stream_index)
             meta = MakeAACCodecSpecificData(profile, sf_index, channel);
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
             break;
-        case CODEC_ID_WMAV1:  // TODO, version?
+        case AV_CODEC_ID_WMAV1:  // TODO, version?
             ALOGV("WMAV1");
             meta = new MetaData;
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_WMA);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             break;
-        case CODEC_ID_WMAV2:
+        case AV_CODEC_ID_WMAV2:
             ALOGV("WMAV2");
             meta = new MetaData;
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_WMA);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             meta->setInt32(kKeyWMAVersion, kTypeWMA);
             break;
-        case CODEC_ID_WMAPRO:
+        case AV_CODEC_ID_WMAPRO:
             ALOGV("WMAPRO");
             meta = new MetaData;
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_WMA);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             meta->setInt32(kKeyWMAVersion, kTypeWMAPro);
             break;
-        case CODEC_ID_WMALOSSLESS:
+        case AV_CODEC_ID_WMALOSSLESS:
             ALOGV("WMALOSSLESS");
             meta = new MetaData;
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_WMA);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             meta->setInt32(kKeyWMAVersion, kTypeWMALossLess);
             break;
-        case CODEC_ID_COOK: // audio codec in RMVB
+        case AV_CODEC_ID_COOK: // audio codec in RMVB
             ALOGV("COOK");
             meta = new MetaData;
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RA);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             break;
-        case CODEC_ID_APE:
+        case AV_CODEC_ID_APE:
             ALOGV("APE");
             meta = new MetaData;
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_APE);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             break;
-        case CODEC_ID_DTS:
+        case AV_CODEC_ID_DTS:
             ALOGV("DTS");
             meta = new MetaData;
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_DTS);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             break;
-        case CODEC_ID_FLAC:
+        case AV_CODEC_ID_FLAC:
             ALOGV("FLAC");
             meta = new MetaData;
             meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC);
@@ -1012,16 +1021,6 @@ int FFmpegExtractor::decode_interrupt_cb(void *ctx)
     return extrator->mAbortRequest;
 }
 
-void FFmpegExtractor::print_error_ex(const char *filename, int err)
-{
-    char errbuf[128];
-    const char *errbuf_ptr = errbuf;
-
-    if (av_strerror(err, errbuf, sizeof(errbuf)) < 0)
-        errbuf_ptr = strerror(AVUNERROR(err));
-    ALOGI("%s: %s\n", filename, errbuf_ptr);
-}
-
 void FFmpegExtractor::buildFileName(const sp<DataSource> &source)
 {
 #if 1
@@ -1129,7 +1128,7 @@ int FFmpegExtractor::initStreams()
     ALOGV("mFilename: %s", mFilename);
     err = avformat_open_input(&mFormatCtx, mFilename, NULL, &format_opts);
     if (err < 0) {
-        print_error_ex(mFilename, err);
+        ALOGE("%s: avformat_open_input failed, err:%s", mFilename, av_err2str(err));
         ret = -1;
         goto fail;
     }
@@ -1148,7 +1147,7 @@ int FFmpegExtractor::initStreams()
 
     err = avformat_find_stream_info(mFormatCtx, opts);
     if (err < 0) {
-        ALOGE("%s: could not find codec parameters\n", mFilename);
+        ALOGE("%s: could not find stream info, err:%s", mFilename, av_err2str(err));
         ret = -1;
         goto fail;
     }
@@ -1607,13 +1606,21 @@ retry:
 
     key = pkt.flags & AV_PKT_FLAG_KEY ? 1 : 0;
     pktTS = pkt.pts; //FIXME AV_NOPTS_VALUE??
-    // use dts when AVI
+
+    //use dts when AVI
     if (pkt.pts == AV_NOPTS_VALUE)
         pktTS = pkt.dts;
 
+    //FIXME, drop, omxcodec requires a positive timestamp! e.g. vorbis
+    if (pktTS != AV_NOPTS_VALUE && pktTS < 0) {
+        ALOGW("drop the packet with negative timestamp(pts:%lld)", pktTS);
+        av_free_packet(&pkt);
+        goto retry;
+    }
+
     if (waitKeyPkt) {
         if (!key) {
-            ALOGV("drop the no key packet");
+            ALOGV("drop the non-key packet");
             av_free_packet(&pkt);
             goto retry;
         } else {
@@ -1731,6 +1738,8 @@ static formatmap FILE_FORMATS[] = {
         {"flac",                    MEDIA_MIMETYPE_CONTAINER_FLAC     },
         {"ac3",                     MEDIA_MIMETYPE_AUDIO_AC3          },
         {"wav",                     MEDIA_MIMETYPE_CONTAINER_WAV      },
+        {"ogg",                     MEDIA_MIMETYPE_CONTAINER_OGG      },
+        {"hevc",                     MEDIA_MIMETYPE_CONTAINER_HEVC    },
 };
 
 static void adjustMPEG4Confidence(AVFormatContext *ic, float *confidence)
@@ -1775,12 +1784,12 @@ static void adjustAudioCodecConfidence(AVFormatContext *ic,
                enum AVCodecID codec_id, float *confidence)
 {
        switch (codec_id) {
-       case CODEC_ID_AC3:
+       case AV_CODEC_ID_AC3:
                ALOGI("ffmpeg can demux ac3 only");
                *confidence = 0.88f;
                break;
-       case CODEC_ID_MP1:
-       case CODEC_ID_MP2:
+       case AV_CODEC_ID_MP1:
+       case AV_CODEC_ID_MP2:
                //TODO. if the other stream(e.g. mp3) is supported by stagefright
                ALOGI("ffmpeg can demux mp1 and mp2 only");
                *confidence = 0.88f;
@@ -1811,7 +1820,7 @@ static void adjustCodecConfidence(AVFormatContext *ic, float *confidence)
                } else if (codec_type == AVMEDIA_TYPE_AUDIO) {
                        haveAudio = true;
                        adjustAudioCodecConfidence(ic, codec_id, confidence);
-                       if (codec_id == CODEC_ID_MP3)
+                       if (codec_id == AV_CODEC_ID_MP3)
                                haveMP3 = true;
                }
        }
@@ -1882,7 +1891,7 @@ static const char *SniffFFMPEGCommon(const char *url, float *confidence)
 
        err = avformat_open_input(&ic, url, NULL, NULL);
        if (err < 0) {
-               ALOGE("avformat_open_input faild, url: %s err: %d", url, err);
+        ALOGE("%s: avformat_open_input failed, err:%s", url, av_err2str(err));
                goto fail;
        }
 
@@ -1890,7 +1899,7 @@ static const char *SniffFFMPEGCommon(const char *url, float *confidence)
        orig_nb_streams = ic->nb_streams;
        err = avformat_find_stream_info(ic, opts);
        if (err < 0) {
-               ALOGE("%s: could not find codec parameters", url);
+        ALOGE("%s: could not find stream info, err:%s", url, av_err2str(err));
                goto fail;
        }
        for (i = 0; i < orig_nb_streams; i++) {
@@ -1993,7 +2002,7 @@ bool SniffFFMPEG(
                *confidence = 0.88f;
        }
 
-       if (*confidence == 0.88f) {
+       if (*confidence > 0.08f) {
                (*meta)->setString("extended-extractor-use", "ffmpegextractor");
        }
 
@@ -2025,6 +2034,8 @@ MediaExtractor *CreateFFmpegExtractor(const sp<DataSource> &source, const char *
             !strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_DTS)       ||
             !strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MP2)       ||
             !strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_RA)        ||
+            !strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_OGG)       ||
+            !strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_HEVC)      ||
             !strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WMA))) {
         ret = new FFmpegExtractor(source);
     }