summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-05-27 16:04:05 +0200
committerMichael Niedermayer <michaelni@gmx.at>2012-05-27 16:04:10 +0200
commit9c27f29a017aa70f7236a6fd513b5ffcde56adb5 (patch)
tree8eaf748b376454ce26b7ae6816e46a2b3973a406
parentfcd08262fdbd5ee4cc0d25d32e331d3f049ad8c2 (diff)
parent7315e40a24e85e7f141db77951a4b14375fde55a (diff)
Merge remote-tracking branch 'cus/stable'
* cus/stable: ffplay: force exit when filter configuration fails ffplay: fix stream cycling if audio decoding fails ffplay: flush codec buffers before freeing filters ffplay: dont destroy packet queues on stream change Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r--ffplay.c115
1 files changed, 77 insertions, 38 deletions
diff --git a/ffplay.c b/ffplay.c
index b57909b854..779c87967a 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -232,6 +232,7 @@ typedef struct VideoState {
#endif
int refresh;
+ int last_video_stream, last_audio_stream, last_subtitle_stream;
} VideoState;
typedef struct AllocEventProps {
@@ -303,13 +304,12 @@ void av_noreturn exit_program(int ret)
exit(ret);
}
-static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
+static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
{
AVPacketList *pkt1;
- /* duplicate the packet */
- if (pkt != &flush_pkt && av_dup_packet(pkt) < 0)
- return -1;
+ if (q->abort_request)
+ return -1;
pkt1 = av_malloc(sizeof(AVPacketList));
if (!pkt1)
@@ -317,11 +317,7 @@ static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
pkt1->pkt = *pkt;
pkt1->next = NULL;
-
- SDL_LockMutex(q->mutex);
-
if (!q->last_pkt)
-
q->first_pkt = pkt1;
else
q->last_pkt->next = pkt1;
@@ -330,9 +326,25 @@ static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
q->size += pkt1->pkt.size + sizeof(*pkt1);
/* XXX: should duplicate packet data in DV case */
SDL_CondSignal(q->cond);
+ return 0;
+}
+
+static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
+{
+ int ret;
+ /* duplicate the packet */
+ if (pkt != &flush_pkt && av_dup_packet(pkt) < 0)
+ return -1;
+
+ SDL_LockMutex(q->mutex);
+ ret = packet_queue_put_private(q, pkt);
SDL_UnlockMutex(q->mutex);
- return 0;
+
+ if (pkt != &flush_pkt && ret < 0)
+ av_free_packet(pkt);
+
+ return ret;
}
/* packet queue handling */
@@ -341,7 +353,7 @@ static void packet_queue_init(PacketQueue *q)
memset(q, 0, sizeof(PacketQueue));
q->mutex = SDL_CreateMutex();
q->cond = SDL_CreateCond();
- packet_queue_put(q, &flush_pkt);
+ q->abort_request = 1;
}
static void packet_queue_flush(PacketQueue *q)
@@ -361,7 +373,7 @@ static void packet_queue_flush(PacketQueue *q)
SDL_UnlockMutex(q->mutex);
}
-static void packet_queue_end(PacketQueue *q)
+static void packet_queue_destroy(PacketQueue *q)
{
packet_queue_flush(q);
SDL_DestroyMutex(q->mutex);
@@ -379,6 +391,14 @@ static void packet_queue_abort(PacketQueue *q)
SDL_UnlockMutex(q->mutex);
}
+static void packet_queue_start(PacketQueue *q)
+{
+ SDL_LockMutex(q->mutex);
+ q->abort_request = 0;
+ packet_queue_put_private(q, &flush_pkt);
+ SDL_UnlockMutex(q->mutex);
+}
+
/* return < 0 if aborted, 0 if no packet and > 0 if packet. */
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
{
@@ -877,6 +897,9 @@ static void stream_close(VideoState *is)
is->abort_request = 1;
SDL_WaitThread(is->read_tid, NULL);
SDL_WaitThread(is->refresh_tid, NULL);
+ packet_queue_destroy(&is->videoq);
+ packet_queue_destroy(&is->audioq);
+ packet_queue_destroy(&is->subtitleq);
/* free all pictures */
for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
@@ -1816,8 +1839,13 @@ static int video_thread(void *arg)
int last_w = is->video_st->codec->width;
int last_h = is->video_st->codec->height;
- if ((ret = configure_video_filters(graph, is, vfilters)) < 0)
+ if ((ret = configure_video_filters(graph, is, vfilters)) < 0) {
+ SDL_Event event;
+ event.type = FF_QUIT_EVENT;
+ event.user.data1 = is;
+ SDL_PushEvent(&event);
goto the_end;
+ }
filt_out = is->out_video_filter;
#endif
@@ -1893,6 +1921,7 @@ static int video_thread(void *arg)
stream_toggle_pause(is);
}
the_end:
+ avcodec_flush_buffers(is->video_st->codec);
#if CONFIG_AVFILTER
av_freep(&vfilters);
avfilter_graph_free(&graph);
@@ -2240,9 +2269,9 @@ static int stream_component_open(VideoState *is, int stream_index)
opts = filter_codec_opts(codec_opts, codec, ic, ic->streams[stream_index]);
switch(avctx->codec_type){
- case AVMEDIA_TYPE_AUDIO : if(audio_codec_name ) codec= avcodec_find_decoder_by_name( audio_codec_name); break;
- case AVMEDIA_TYPE_SUBTITLE: if(subtitle_codec_name) codec= avcodec_find_decoder_by_name(subtitle_codec_name); break;
- case AVMEDIA_TYPE_VIDEO : if(video_codec_name ) codec= avcodec_find_decoder_by_name( video_codec_name); break;
+ case AVMEDIA_TYPE_AUDIO : is->last_audio_stream = stream_index; if(audio_codec_name ) codec= avcodec_find_decoder_by_name( audio_codec_name); break;
+ case AVMEDIA_TYPE_SUBTITLE: is->last_subtitle_stream = stream_index; if(subtitle_codec_name) codec= avcodec_find_decoder_by_name(subtitle_codec_name); break;
+ case AVMEDIA_TYPE_VIDEO : is->last_video_stream = stream_index; if(video_codec_name ) codec= avcodec_find_decoder_by_name( video_codec_name); break;
}
if (!codec)
return -1;
@@ -2343,20 +2372,20 @@ static int stream_component_open(VideoState *is, int stream_index)
is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / wanted_spec.freq;
memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
- packet_queue_init(&is->audioq);
+ packet_queue_start(&is->audioq);
SDL_PauseAudio(0);
break;
case AVMEDIA_TYPE_VIDEO:
is->video_stream = stream_index;
is->video_st = ic->streams[stream_index];
- packet_queue_init(&is->videoq);
+ packet_queue_start(&is->videoq);
is->video_tid = SDL_CreateThread(video_thread, is);
break;
case AVMEDIA_TYPE_SUBTITLE:
is->subtitle_stream = stream_index;
is->subtitle_st = ic->streams[stream_index];
- packet_queue_init(&is->subtitleq);
+ packet_queue_start(&is->subtitleq);
is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
break;
@@ -2381,7 +2410,7 @@ static void stream_component_close(VideoState *is, int stream_index)
SDL_CloseAudio();
- packet_queue_end(&is->audioq);
+ packet_queue_flush(&is->audioq);
av_free_packet(&is->audio_pkt);
if (is->swr_ctx)
swr_free(&is->swr_ctx);
@@ -2407,7 +2436,7 @@ static void stream_component_close(VideoState *is, int stream_index)
SDL_WaitThread(is->video_tid, NULL);
- packet_queue_end(&is->videoq);
+ packet_queue_flush(&is->videoq);
break;
case AVMEDIA_TYPE_SUBTITLE:
packet_queue_abort(&is->subtitleq);
@@ -2422,7 +2451,7 @@ static void stream_component_close(VideoState *is, int stream_index)
SDL_WaitThread(is->subtitle_tid, NULL);
- packet_queue_end(&is->subtitleq);
+ packet_queue_flush(&is->subtitleq);
break;
default:
break;
@@ -2469,9 +2498,9 @@ static int read_thread(void *arg)
int orig_nb_streams;
memset(st_index, -1, sizeof(st_index));
- is->video_stream = -1;
- is->audio_stream = -1;
- is->subtitle_stream = -1;
+ is->last_video_stream = is->video_stream = -1;
+ is->last_audio_stream = is->audio_stream = -1;
+ is->last_subtitle_stream = is->subtitle_stream = -1;
ic = avformat_alloc_context();
ic->interrupt_callback.callback = decode_interrupt_cb;
@@ -2625,9 +2654,9 @@ static int read_thread(void *arg)
/* if the queue are full, no need to read more */
if ( is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
- || ( (is->audioq .nb_packets > MIN_FRAMES || is->audio_stream < 0)
- && (is->videoq .nb_packets > MIN_FRAMES || is->video_stream < 0)
- && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream < 0))) {
+ || ( (is->audioq .nb_packets > MIN_FRAMES || is->audio_stream < 0 || is->audioq.abort_request)
+ && (is->videoq .nb_packets > MIN_FRAMES || is->video_stream < 0 || is->videoq.abort_request)
+ && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream < 0 || is->subtitleq.abort_request))) {
/* wait 10 ms */
SDL_Delay(10);
continue;
@@ -2732,6 +2761,10 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
is->subpq_mutex = SDL_CreateMutex();
is->subpq_cond = SDL_CreateCond();
+ packet_queue_init(&is->videoq);
+ packet_queue_init(&is->audioq);
+ packet_queue_init(&is->subtitleq);
+
is->av_sync_type = av_sync_type;
is->read_tid = SDL_CreateThread(read_thread, is);
if (!is->read_tid) {
@@ -2745,16 +2778,19 @@ static void stream_cycle_channel(VideoState *is, int codec_type)
{
AVFormatContext *ic = is->ic;
int start_index, stream_index;
+ int old_index;
AVStream *st;
- if (codec_type == AVMEDIA_TYPE_VIDEO)
- start_index = is->video_stream;
- else if (codec_type == AVMEDIA_TYPE_AUDIO)
- start_index = is->audio_stream;
- else
- start_index = is->subtitle_stream;
- if (start_index < (codec_type == AVMEDIA_TYPE_SUBTITLE ? -1 : 0))
- return;
+ if (codec_type == AVMEDIA_TYPE_VIDEO) {
+ start_index = is->last_video_stream;
+ old_index = is->video_stream;
+ } else if (codec_type == AVMEDIA_TYPE_AUDIO) {
+ start_index = is->last_audio_stream;
+ old_index = is->audio_stream;
+ } else {
+ start_index = is->last_subtitle_stream;
+ old_index = is->subtitle_stream;
+ }
stream_index = start_index;
for (;;) {
if (++stream_index >= is->ic->nb_streams)
@@ -2762,9 +2798,12 @@ static void stream_cycle_channel(VideoState *is, int codec_type)
if (codec_type == AVMEDIA_TYPE_SUBTITLE)
{
stream_index = -1;
+ is->last_subtitle_stream = -1;
goto the_end;
- } else
- stream_index = 0;
+ }
+ if (start_index == -1)
+ return;
+ stream_index = 0;
}
if (stream_index == start_index)
return;
@@ -2786,7 +2825,7 @@ static void stream_cycle_channel(VideoState *is, int codec_type)
}
}
the_end:
- stream_component_close(is, start_index);
+ stream_component_close(is, old_index);
stream_component_open(is, stream_index);
}