From 09a49e8919ddd31d0255f46ad1c3d19be7bb5ed1 Mon Sep 17 00:00:00 2001 From: Mohamed Naufal Date: Fri, 7 Oct 2011 17:01:08 +0530 Subject: [PATCH 1/5] libstagefright: set the correct frame size --- libavcodec/libstagefright.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/libstagefright.cpp b/libavcodec/libstagefright.cpp index 2022bab37e..6989357f53 100644 --- a/libavcodec/libstagefright.cpp +++ b/libavcodec/libstagefright.cpp @@ -311,7 +311,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) @@ -324,8 +324,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; From 23ea48f2f7caebbaac19a6a4d8c931c06e9bd2df Mon Sep 17 00:00:00 2001 From: Mohamed Naufal Date: Fri, 7 Oct 2011 17:59:29 +0530 Subject: [PATCH 2/5] libstagefright: return EOS if CustomSource::read() is called after decode_thread() returns --- libavcodec/libstagefright.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/libstagefright.cpp b/libavcodec/libstagefright.cpp index 6989357f53..7f3b785211 100644 --- a/libavcodec/libstagefright.cpp +++ b/libavcodec/libstagefright.cpp @@ -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()) From 295f13953dc57be8c2ad7e41f6254d0a036582a8 Mon Sep 17 00:00:00 2001 From: Mohamed Naufal Date: Fri, 7 Oct 2011 17:21:09 +0530 Subject: [PATCH 3/5] libstagefright: limit the output queue size --- libavcodec/libstagefright.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/libavcodec/libstagefright.cpp b/libavcodec/libstagefright.cpp index 7f3b785211..1f8bdc4d59 100644 --- a/libavcodec/libstagefright.cpp +++ b/libavcodec/libstagefright.cpp @@ -174,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); @@ -435,6 +443,17 @@ static av_cold int Stagefright_close(AVCodecContext *avctx) 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. From fedbf9177c6e22ca109f37ff55ac3097eb152edd Mon Sep 17 00:00:00 2001 From: Mohamed Naufal Date: Fri, 7 Oct 2011 18:05:34 +0530 Subject: [PATCH 4/5] libstagefright: mark the dummy frame as keyframe. This makes sure decoder->read() returns if it is the first frame fed. --- libavcodec/libstagefright.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/libstagefright.cpp b/libavcodec/libstagefright.cpp index 1f8bdc4d59..f6dad67ddc 100644 --- a/libavcodec/libstagefright.cpp +++ b/libavcodec/libstagefright.cpp @@ -460,6 +460,7 @@ static av_cold int Stagefright_close(AVCodecContext *avctx) 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); From a85996d834ffa66a3d73c9d4610d078ec7f57e61 Mon Sep 17 00:00:00 2001 From: Mohamed Naufal Date: Fri, 7 Oct 2011 18:07:16 +0530 Subject: [PATCH 5/5] libstagefright: start decode_thread() only after decode_frame() is called at least once. This prevents the situation where EOS is passed as the first frame to the h/w decoder and thus avoids a potential crash. --- libavcodec/libstagefright.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libavcodec/libstagefright.cpp b/libavcodec/libstagefright.cpp index f6dad67ddc..e20ff52ca7 100644 --- a/libavcodec/libstagefright.cpp +++ b/libavcodec/libstagefright.cpp @@ -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; @@ -274,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: @@ -303,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); @@ -440,6 +444,7 @@ static av_cold int Stagefright_close(AVCodecContext *avctx) StagefrightContext *s = (StagefrightContext*)avctx->priv_data; Frame *frame; + if (s->thread_started) { if (!s->thread_exited) { s->stop_decode = 1; @@ -482,6 +487,9 @@ static av_cold int Stagefright_close(AVCodecContext *avctx) 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(); s->in_queue->erase(s->in_queue->begin());