OSDN Git Service

stagefright-plugins: Fix crash if nal size is not 3/4
[android-x86/external-stagefright-plugins.git] / extractor / FFmpegExtractor.cpp
index 403bef6..1a27f68 100644 (file)
@@ -1269,7 +1269,7 @@ void FFmpegExtractor::readerEntry() {
                     memcpy(avctx->extradata, pkt->data, avctx->extradata_size);
                     memset(avctx->extradata + i, 0, FF_INPUT_BUFFER_PADDING_SIZE);
                 } else {
-                    av_free_packet(pkt);
+                    av_packet_unref(pkt);
                     continue;
                 }
 
@@ -1290,7 +1290,7 @@ void FFmpegExtractor::readerEntry() {
                                    pkt->data, pkt->size, pkt->flags & AV_PKT_FLAG_KEY);
 
                 if (ret < 0 ||!outbuf_size) {
-                    av_free_packet(pkt);
+                    av_packet_unref(pkt);
                     continue;
                 }
                 if (outbuf && outbuf != pkt->data) {
@@ -1300,7 +1300,7 @@ void FFmpegExtractor::readerEntry() {
             }
             if (mDefersToCreateAudioTrack) {
                 if (avctx->extradata_size <= 0) {
-                    av_free_packet(pkt);
+                    av_packet_unref(pkt);
                     continue;
                 }
                 stream_component_open(mAudioStreamIdx);
@@ -1317,7 +1317,7 @@ void FFmpegExtractor::readerEntry() {
         } else if (pkt->stream_index == mVideoStreamIdx) {
             packet_queue_put(&mVideoQ, pkt);
         } else {
-            av_free_packet(pkt);
+            av_packet_unref(pkt);
         }
     }
 
@@ -1436,6 +1436,7 @@ status_t FFmpegSource::read(
     int64_t timeUs = AV_NOPTS_VALUE;
     int key = 0;
     status_t status = OK;
+    int max_negative_time_frame = 100;
 
     int64_t startTimeUs = mStream->start_time == AV_NOPTS_VALUE ? 0 :
         av_rescale_q(mStream->start_time, mStream->time_base, AV_TIME_BASE_Q);
@@ -1460,7 +1461,7 @@ retry:
 
     if (seeking) {
         if (pkt.data != mQueue->flush_pkt.data) {
-            av_free_packet(&pkt);
+            av_packet_unref(&pkt);
             goto retry;
         } else {
             seeking = false;
@@ -1472,12 +1473,12 @@ retry:
 
     if (pkt.data == mQueue->flush_pkt.data) {
         ALOGV("read %s flush pkt", av_get_media_type_string(mMediaType));
-        av_free_packet(&pkt);
+        av_packet_unref(&pkt);
         mFirstKeyPktTimestamp = AV_NOPTS_VALUE;
         goto retry;
     } else if (pkt.data == NULL && pkt.size == 0) {
         ALOGD("read %s eos pkt", av_get_media_type_string(mMediaType));
-        av_free_packet(&pkt);
+        av_packet_unref(&pkt);
         mExtractor->reachedEOS(mMediaType);
         return ERROR_END_OF_STREAM;
     }
@@ -1488,7 +1489,7 @@ retry:
     if (waitKeyPkt) {
         if (!key) {
             ALOGV("drop the non-key packet");
-            av_free_packet(&pkt);
+            av_packet_unref(&pkt);
             goto retry;
         } else {
             ALOGV("~~~~~~ got the key packet");
@@ -1508,7 +1509,13 @@ retry:
     //copy data
     if ((mIsAVC || mIsHEVC) && mNal2AnnexB) {
         /* This only works for NAL sizes 3-4 */
-        CHECK(mNALLengthSize == 3 || mNALLengthSize == 4);
+        if ((mNALLengthSize != 3) && (mNALLengthSize != 4)) {
+            ALOGE("cannot use convertNal2AnnexB, nal size: %d", mNALLengthSize);
+            mediaBuffer->release();
+            mediaBuffer = NULL;
+            av_packet_unref(&pkt);
+            return ERROR_MALFORMED;
+        }
 
         uint8_t *dst = (uint8_t *)mediaBuffer->data();
         /* Convert H.264 NAL format to annex b */
@@ -1517,7 +1524,7 @@ retry:
             ALOGE("convertNal2AnnexB failed");
             mediaBuffer->release();
             mediaBuffer = NULL;
-            av_free_packet(&pkt);
+            av_packet_unref(&pkt);
             return ERROR_MALFORMED;
         }
     } else {
@@ -1540,8 +1547,13 @@ retry:
                , timeUs, startTimeUs, pkt.dts, pkt.pts);
         mediaBuffer->release();
         mediaBuffer = NULL;
-        av_free_packet(&pkt);
-        return ERROR_MALFORMED;
+        av_packet_unref(&pkt);
+        if (max_negative_time_frame-- > 0) {
+            goto retry;
+        } else {
+            ALOGE("too many negative timestamp packets, abort decoding");
+            return ERROR_MALFORMED;
+        }
     }
 
     // predict the next PTS to use for exact-frame seek below
@@ -1584,7 +1596,7 @@ retry:
 
     *buffer = mediaBuffer;
 
-    av_free_packet(&pkt);
+    av_packet_unref(&pkt);
 
     return OK;
 }
@@ -2150,6 +2162,9 @@ bool SniffFFMPEG(
     // This is a heavyweight sniffer, don't invoke it if Stagefright knows
     // what it is doing already.
     if (mimeType != NULL && confidence != NULL) {
+        if (*mimeType == "application/ogg") {
+            return false;
+        }
         if (*confidence > 0.8f) {
             return false;
         }