OSDN Git Service

add HEVC(H.265) decoder. plz sync:
[android-x86/external-stagefright-plugins.git] / libstagefright / FFmpegExtractor / FFmpegExtractor.cpp
index 3fcd33e..08fa7a2 100644 (file)
@@ -375,6 +375,7 @@ static uint32_t get_sample_rate(const uint8_t sf_index)
 
 int FFmpegExtractor::check_extradata(AVCodecContext *avctx)
 {
+    enum AVCodecID codec_id = AV_CODEC_ID_NONE;
     const char *name = NULL;
     bool *defersToCreateTrack = NULL;
     AVBitStreamFilterContext **bsfc = NULL;
@@ -388,21 +389,19 @@ int FFmpegExtractor::check_extradata(AVCodecContext *avctx)
         defersToCreateTrack = &mDefersToCreateAudioTrack;
     }
 
+       codec_id = avctx->codec_id;
+
     // ignore extradata
-    if (avctx->codec_id == CODEC_ID_MP3 ||
-            avctx->codec_id == CODEC_ID_MP1   ||
-            avctx->codec_id == CODEC_ID_MP2   ||
-            avctx->codec_id == CODEC_ID_AC3   ||
-            avctx->codec_id == CODEC_ID_DTS   ||
-            avctx->codec_id == CODEC_ID_H263  ||
-            avctx->codec_id == CODEC_ID_H263P ||
-            avctx->codec_id == CODEC_ID_H263I ||
-            avctx->codec_id == CODEC_ID_FLV1  ||
-            avctx->codec_id == CODEC_ID_WMV1)
+    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 (avctx->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",
@@ -414,7 +413,7 @@ int FFmpegExtractor::check_extradata(AVCodecContext *avctx)
         return 1;
     }
 
-    if (avctx->codec_id == CODEC_ID_AAC) {
+    if (codec_id == AV_CODEC_ID_AAC) {
         name = "aac_adtstoasc";
     }
 
@@ -457,6 +456,55 @@ void FFmpegExtractor::printTime(int64_t time)
         hours, mins, secs, (100 * us) / AV_TIME_BASE);
 }
 
+bool FFmpegExtractor::is_codec_supported(enum AVCodecID codec_id)
+{
+    bool supported = false;
+
+    switch(codec_id) {
+    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(%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;
+        break;
+    }
+
+       return supported;
+}
+
 int FFmpegExtractor::stream_component_open(int stream_index)
 {
     AVCodecContext *avctx = NULL;
@@ -473,47 +521,13 @@ int FFmpegExtractor::stream_component_open(int stream_index)
         return -1;
     avctx = mFormatCtx->streams[stream_index]->codec;
 
-    switch(avctx->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:
-        supported = true;
-        break;
-    default:
-        supported = false;
-        break;
-    }
+    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);
@@ -527,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:
@@ -536,7 +550,7 @@ int FFmpegExtractor::stream_component_open(int stream_index)
         if (mVideoStream == NULL)
             mVideoStream = mFormatCtx->streams[stream_index];
         if (!mVideoQInited) {
-           packet_queue_init(&mVideoQ);
+               packet_queue_init(&mVideoQ);
             mVideoQInited = true;
         }
 
@@ -563,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
@@ -599,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);
             {
@@ -609,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);
@@ -626,52 +640,65 @@ 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:
-            CHECK(!"Should not be here. Unsupported codec.");
+            ALOGD("unsuppoted video codec(id:%d, name:%s), but give it a chance",
+                    avctx->codec_id, avcodec_get_name(avctx->codec_id));
+            meta = new MetaData;
+            meta->setInt32(kKeyCodecId, avctx->codec_id);
+            meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_FFMPEG);
+            if (avctx->extradata_size > 0) {
+                meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+            }
+            //CHECK(!"Should not be here. Unsupported codec.");
             break;
         }
 
@@ -686,6 +713,11 @@ int FFmpegExtractor::stream_component_open(int stream_index)
             int64_t duration = mVideoStream->duration * av_q2d(mVideoStream->time_base) * 1000000;
             printTime(duration);
             ALOGV("video startTime: %lld", mVideoStream->start_time);
+            if (mVideoStream->start_time != AV_NOPTS_VALUE) {
+                ALOGV("video startTime:%lld", mVideoStream->start_time);
+            } else {
+                ALOGV("video startTime:N/A");
+            }
             meta->setInt64(kKeyDuration, duration);
         } else {
             // default when no stream duration
@@ -723,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;
@@ -777,59 +810,67 @@ 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);
             meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
             break;
         default:
-            CHECK(!"Should not be here. Unsupported codec.");
+            ALOGD("unsuppoted audio codec(id:%d, name:%s), but give it a chance",
+                    avctx->codec_id, avcodec_get_name(avctx->codec_id));
+            meta = new MetaData;
+            meta->setInt32(kKeyCodecId, avctx->codec_id);
+            meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FFMPEG);
+            if (avctx->extradata_size > 0) {
+                meta->setData(kKeyRawCodecSpecificData, 0, avctx->extradata, avctx->extradata_size);
+            }
+            //CHECK(!"Should not be here. Unsupported codec.");
             break;
         }
 
@@ -838,15 +879,20 @@ int FFmpegExtractor::stream_component_open(int stream_index)
                 avctx->bit_rate, avctx->sample_rate, avctx->channels,
                 avctx->bits_per_coded_sample, avctx->block_align);
 
-        meta->setInt32(kKeySampleRate, avctx->sample_rate);
         meta->setInt32(kKeyChannelCount, avctx->channels);
-        meta->setInt32(kKeyBitspersample, avctx->bits_per_coded_sample);
         meta->setInt32(kKeyBitRate, avctx->bit_rate);
+        meta->setInt32(kKeyBitspersample, avctx->bits_per_coded_sample);
+        meta->setInt32(kKeySampleRate, avctx->sample_rate);
         meta->setInt32(kKeyBlockAlign, avctx->block_align);
+        meta->setInt32(kKeySampleFormat, avctx->sample_fmt);
         if (mAudioStream->duration != AV_NOPTS_VALUE) {
             int64_t duration = mAudioStream->duration * av_q2d(mAudioStream->time_base) * 1000000;
             printTime(duration);
-            ALOGV("audio startTime: %lld", mAudioStream->start_time);
+            if (mAudioStream->start_time != AV_NOPTS_VALUE) {
+                ALOGV("audio startTime:%lld", mAudioStream->start_time);
+            } else {
+                ALOGV("audio startTime:N/A");
+            }
             meta->setInt64(kKeyDuration, duration);
         } else {
             // default when no stream duration
@@ -975,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
@@ -1092,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;
     }
@@ -1111,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;
     }
@@ -1523,8 +1559,8 @@ status_t FFmpegExtractor::Track::read(
     ReadOptions::SeekMode mode;
     int64_t pktTS = AV_NOPTS_VALUE;
     int64_t seekTimeUs = AV_NOPTS_VALUE;
-    int64_t timeUs;
-    int key;
+    int64_t timeUs = AV_NOPTS_VALUE;
+    int key = 0;
     status_t status = OK;
 
     if (options && options->getSeekTo(&seekTimeUs, &mode)) {
@@ -1569,14 +1605,22 @@ retry:
     }
 
     key = pkt.flags & AV_PKT_FLAG_KEY ? 1 : 0;
-    pktTS = pkt.pts;
-    // use dts when AVI
+    pktTS = pkt.pts; //FIXME AV_NOPTS_VALUE??
+
+    //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 {
@@ -1585,12 +1629,12 @@ retry:
         }
     }
 
-    if (mFirstKeyPktTimestamp == AV_NOPTS_VALUE) {
+    if (pktTS != AV_NOPTS_VALUE && mFirstKeyPktTimestamp == AV_NOPTS_VALUE) {
         // update the first key timestamp
         mFirstKeyPktTimestamp = pktTS;
     }
      
-    if (pktTS < mFirstKeyPktTimestamp) {
+    if (pktTS != AV_NOPTS_VALUE && pktTS < mFirstKeyPktTimestamp) {
             ALOGV("drop the packet with the backward timestamp, maybe they are B-frames after I-frame ^_^");
             av_free_packet(&pkt);
             goto retry;
@@ -1648,11 +1692,18 @@ retry:
     }
 
     int64_t start_time = mStream->start_time != AV_NOPTS_VALUE ? mStream->start_time : 0;
-    timeUs = (int64_t)((pktTS - start_time) * av_q2d(mStream->time_base) * 1000000);
+    if (pktTS != AV_NOPTS_VALUE)
+        timeUs = (int64_t)((pktTS - start_time) * av_q2d(mStream->time_base) * 1000000);
+    else
+        timeUs = SF_NOPTS_VALUE; //FIXME AV_NOPTS_VALUE is negative, but stagefright need positive
 
 #if DEBUG_PKT
-    ALOGV("read %s pkt, size: %d, key: %d, pts: %lld, dts: %lld, timeUs[-startTime]: %llu us (%.2f secs)",
-        av_get_media_type_string(mMediaType), pkt.size, key, pkt.pts, pkt.dts, timeUs, timeUs/1E6);
+    if (pktTS != AV_NOPTS_VALUE)
+        ALOGV("read %s pkt, size:%d, key:%d, pts:%lld, dts:%lld, timeUs[-startTime]:%lld us (%.2f secs)",
+            av_get_media_type_string(mMediaType), pkt.size, key, pkt.pts, pkt.dts, timeUs, timeUs/1E6);
+    else
+        ALOGV("read %s pkt, size:%d, key:%d, pts:N/A, dts:N/A, timeUs[-startTime]:N/A",
+            av_get_media_type_string(mMediaType), pkt.size, key);
 #endif
 
     mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
@@ -1687,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)
@@ -1731,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;
@@ -1767,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;
                }
        }
@@ -1838,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;
        }
 
@@ -1846,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++) {
@@ -1949,7 +2002,7 @@ bool SniffFFMPEG(
                *confidence = 0.88f;
        }
 
-       if (*confidence == 0.88f) {
+       if (*confidence > 0.08f) {
                (*meta)->setString("extended-extractor-use", "ffmpegextractor");
        }
 
@@ -1981,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);
     }