]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/libstagefright.cpp
Set Chronomaster DFA palette opaque.
[ffmpeg] / libavcodec / libstagefright.cpp
index e31a2ec7b3a8a470d6e107dd41ae11dcfc74dc42..e29a377311eb0deba33be63a8d8ae789821a1912 100644 (file)
@@ -5,20 +5,20 @@
  * Copyright (C) 2011 Mohamed Naufal
  * Copyright (C) 2011 Martin Storsjö
  *
- * This file is part of Libav.
+ * This file is part of FFmpeg.
  *
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
@@ -58,7 +58,7 @@ struct StagefrightContext {
     AVBitStreamFilterContext *bsfc;
     uint8_t* orig_extradata;
     int orig_extradata_size;
-    sp<MediaSource> source;
+    sp<MediaSource> *source;
     List<Frame*> *in_queue, *out_queue;
     pthread_mutex_t in_mutex, out_mutex;
     pthread_cond_t condition;
@@ -66,7 +66,7 @@ struct StagefrightContext {
 
     Frame *end_frame;
     bool source_done;
-    volatile sig_atomic_t thread_exited, stop_decode;
+    volatile sig_atomic_t thread_started, thread_exited, stop_decode;
 
     AVFrame ret_frame;
 
@@ -74,7 +74,7 @@ struct StagefrightContext {
     int dummy_bufsize;
 
     OMXClient *client;
-    sp<MediaSource> decoder;
+    sp<MediaSource> *decoder;
     const char *decoder_component;
 };
 
@@ -104,6 +104,8 @@ public:
         Frame *frame;
         status_t ret;
 
+        if (s->thread_exited)
+            return ERROR_END_OF_STREAM;
         pthread_mutex_lock(&s->in_mutex);
 
         while (s->in_queue->empty())
@@ -156,9 +158,9 @@ void* decode_thread(void *arg)
             decode_done   = 1;
             s->end_frame  = NULL;
         } else {
-            frame->status = s->decoder->read(&buffer);
+            frame->status = (*s->decoder)->read(&buffer);
             if (frame->status == OK) {
-                sp<MetaData> outFormat = s->decoder->getFormat();
+                sp<MetaData> outFormat = (*s->decoder)->getFormat();
                 outFormat->findInt32(kKeyWidth , &frame->w);
                 outFormat->findInt32(kKeyHeight, &frame->h);
                 frame->size    = buffer->range_length();
@@ -172,7 +174,15 @@ void* decode_thread(void *arg)
                 decode_done = 1;
             }
         }
-        pthread_mutex_lock(&s->out_mutex);
+        while (true) {
+            pthread_mutex_lock(&s->out_mutex);
+            if (s->out_queue->size() >= 10) {
+                pthread_mutex_unlock(&s->out_mutex);
+                usleep(10000);
+                continue;
+            }
+            break;
+        }
         s->out_queue->push_back(frame);
         pthread_mutex_unlock(&s->out_mutex);
     } while (!decode_done && !s->stop_decode);
@@ -220,7 +230,8 @@ static av_cold int Stagefright_init(AVCodecContext *avctx)
 
     android::ProcessState::self()->startThreadPool();
 
-    s->source    = new CustomSource(avctx, meta);
+    s->source    = new sp<MediaSource>();
+    *s->source   = new CustomSource(avctx, meta);
     s->in_queue  = new List<Frame*>;
     s->out_queue = new List<Frame*>;
     s->client    = new OMXClient;
@@ -237,17 +248,18 @@ static av_cold int Stagefright_init(AVCodecContext *avctx)
         goto fail;
     }
 
-    s->decoder = OMXCodec::Create(s->client->interface(), meta,
-                                  false, s->source, NULL,
+    s->decoder  = new sp<MediaSource>();
+    *s->decoder = OMXCodec::Create(s->client->interface(), meta,
+                                  false, *s->source, NULL,
                                   OMXCodec::kClientNeedsFramebuffer);
-    if (s->decoder->start() !=  OK) {
+    if ((*s->decoder)->start() !=  OK) {
         av_log(avctx, AV_LOG_ERROR, "Cannot start decoder\n");
         ret = -1;
         s->client->disconnect();
         goto fail;
     }
 
-    outFormat = s->decoder->getFormat();
+    outFormat = (*s->decoder)->getFormat();
     outFormat->findInt32(kKeyColorFormat, &colorFormat);
     if (colorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar ||
         colorFormat == OMX_COLOR_FormatYUV420SemiPlanar)
@@ -262,7 +274,6 @@ static av_cold int Stagefright_init(AVCodecContext *avctx)
     pthread_mutex_init(&s->in_mutex, NULL);
     pthread_mutex_init(&s->out_mutex, NULL);
     pthread_cond_init(&s->condition, NULL);
-    pthread_create(&s->decode_thread_id, NULL, &decode_thread, avctx);
     return 0;
 
 fail:
@@ -291,6 +302,11 @@ static int Stagefright_decode_frame(AVCodecContext *avctx, void *data,
     AVPacket pkt = *avpkt;
     int ret;
 
+    if (!s->thread_started) {
+        pthread_create(&s->decode_thread_id, NULL, &decode_thread, avctx);
+        s->thread_started = true;
+    }
+
     if (avpkt && avpkt->data) {
         av_bitstream_filter_filter(s->bsfc, avctx, NULL, &pkt.data, &pkt.size,
                                    avpkt->data, avpkt->size, avpkt->flags & AV_PKT_FLAG_KEY);
@@ -309,7 +325,7 @@ static int Stagefright_decode_frame(AVCodecContext *avctx, void *data,
         frame = (Frame*)av_mallocz(sizeof(Frame));
         if (avpkt->data) {
             frame->status  = OK;
-            frame->size    = orig_size;
+            frame->size    = avpkt->size;
             // Stagefright can't handle negative timestamps -
             // if needed, work around this by offsetting them manually?
             if (avpkt->pts >= 0)
@@ -322,8 +338,10 @@ static int Stagefright_decode_frame(AVCodecContext *avctx, void *data,
             }
             uint8_t *ptr = avpkt->data;
             // The OMX.SEC decoder fails without this.
-            if (avpkt->size == orig_size + avctx->extradata_size)
+            if (avpkt->size == orig_size + avctx->extradata_size) {
                 ptr += avctx->extradata_size;
+                frame->size = orig_size;
+            }
             memcpy(frame->buffer, ptr, orig_size);
         } else {
             frame->status  = ERROR_END_OF_STREAM;
@@ -426,35 +444,51 @@ static av_cold int Stagefright_close(AVCodecContext *avctx)
     StagefrightContext *s = (StagefrightContext*)avctx->priv_data;
     Frame *frame;
 
-    if (!s->thread_exited) {
-        s->stop_decode = 1;
+    if (s->thread_started) {
+        if (!s->thread_exited) {
+            s->stop_decode = 1;
+
+            // Make sure decode_thread() doesn't get stuck
+            pthread_mutex_lock(&s->out_mutex);
+            while (!s->out_queue->empty()) {
+                frame = *s->out_queue->begin();
+                s->out_queue->erase(s->out_queue->begin());
+                if (frame->size)
+                    frame->mbuffer->release();
+                av_freep(&frame);
+            }
+            pthread_mutex_unlock(&s->out_mutex);
+
+            // Feed a dummy frame prior to signalling EOF.
+            // This is required to terminate the decoder(OMX.SEC)
+            // when only one frame is read during stream info detection.
+            if (s->dummy_buf && (frame = (Frame*)av_mallocz(sizeof(Frame)))) {
+                frame->status = OK;
+                frame->size   = s->dummy_bufsize;
+                frame->key    = 1;
+                frame->buffer = s->dummy_buf;
+                pthread_mutex_lock(&s->in_mutex);
+                s->in_queue->push_back(frame);
+                pthread_cond_signal(&s->condition);
+                pthread_mutex_unlock(&s->in_mutex);
+                s->dummy_buf = NULL;
+            }
 
-        // Feed a dummy frame prior to signalling EOF.
-        // This is required to terminate the decoder(OMX.SEC)
-        // when only one frame is read during stream info detection.
-        if (s->dummy_buf && (frame = (Frame*)av_mallocz(sizeof(Frame)))) {
-            frame->status = OK;
-            frame->size   = s->dummy_bufsize;
-            frame->buffer = s->dummy_buf;
             pthread_mutex_lock(&s->in_mutex);
-            s->in_queue->push_back(frame);
+            s->end_frame->status = ERROR_END_OF_STREAM;
+            s->in_queue->push_back(s->end_frame);
             pthread_cond_signal(&s->condition);
             pthread_mutex_unlock(&s->in_mutex);
-            s->dummy_buf = NULL;
+            s->end_frame = NULL;
         }
 
-        pthread_mutex_lock(&s->in_mutex);
-        s->end_frame->status = ERROR_END_OF_STREAM;
-        s->in_queue->push_back(s->end_frame);
-        pthread_cond_signal(&s->condition);
-        pthread_mutex_unlock(&s->in_mutex);
-        s->end_frame = NULL;
-    }
+        pthread_join(s->decode_thread_id, NULL);
 
-    pthread_join(s->decode_thread_id, NULL);
+        if (s->ret_frame.data[0])
+            avctx->release_buffer(avctx, &s->ret_frame);
 
-    if (s->ret_frame.data[0])
-        avctx->release_buffer(avctx, &s->ret_frame);
+        s->thread_started = false;
+    }
 
     while (!s->in_queue->empty()) {
         frame = *s->in_queue->begin();
@@ -472,7 +506,7 @@ static av_cold int Stagefright_close(AVCodecContext *avctx)
         av_freep(&frame);
     }
 
-    s->decoder->stop();
+    (*s->decoder)->stop();
     s->client->disconnect();
 
     if (s->decoder_component)
@@ -490,6 +524,8 @@ static av_cold int Stagefright_close(AVCodecContext *avctx)
     delete s->in_queue;
     delete s->out_queue;
     delete s->client;
+    delete s->decoder;
+    delete s->source;
 
     pthread_mutex_destroy(&s->in_mutex);
     pthread_mutex_destroy(&s->out_mutex);