Commit 9c27f29a authored by Michael Niedermayer's avatar Michael Niedermayer

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: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents fcd08262 7315e40a
...@@ -232,6 +232,7 @@ typedef struct VideoState { ...@@ -232,6 +232,7 @@ typedef struct VideoState {
#endif #endif
int refresh; int refresh;
int last_video_stream, last_audio_stream, last_subtitle_stream;
} VideoState; } VideoState;
typedef struct AllocEventProps { typedef struct AllocEventProps {
...@@ -303,12 +304,11 @@ void av_noreturn exit_program(int ret) ...@@ -303,12 +304,11 @@ void av_noreturn exit_program(int ret)
exit(ret); exit(ret);
} }
static int packet_queue_put(PacketQueue *q, AVPacket *pkt) static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
{ {
AVPacketList *pkt1; AVPacketList *pkt1;
/* duplicate the packet */ if (q->abort_request)
if (pkt != &flush_pkt && av_dup_packet(pkt) < 0)
return -1; return -1;
pkt1 = av_malloc(sizeof(AVPacketList)); pkt1 = av_malloc(sizeof(AVPacketList));
...@@ -317,11 +317,7 @@ static int packet_queue_put(PacketQueue *q, AVPacket *pkt) ...@@ -317,11 +317,7 @@ static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
pkt1->pkt = *pkt; pkt1->pkt = *pkt;
pkt1->next = NULL; pkt1->next = NULL;
SDL_LockMutex(q->mutex);
if (!q->last_pkt) if (!q->last_pkt)
q->first_pkt = pkt1; q->first_pkt = pkt1;
else else
q->last_pkt->next = pkt1; q->last_pkt->next = pkt1;
...@@ -330,9 +326,25 @@ static int packet_queue_put(PacketQueue *q, AVPacket *pkt) ...@@ -330,9 +326,25 @@ static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
q->size += pkt1->pkt.size + sizeof(*pkt1); q->size += pkt1->pkt.size + sizeof(*pkt1);
/* XXX: should duplicate packet data in DV case */ /* XXX: should duplicate packet data in DV case */
SDL_CondSignal(q->cond); 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); SDL_UnlockMutex(q->mutex);
return 0;
if (pkt != &flush_pkt && ret < 0)
av_free_packet(pkt);
return ret;
} }
/* packet queue handling */ /* packet queue handling */
...@@ -341,7 +353,7 @@ static void packet_queue_init(PacketQueue *q) ...@@ -341,7 +353,7 @@ static void packet_queue_init(PacketQueue *q)
memset(q, 0, sizeof(PacketQueue)); memset(q, 0, sizeof(PacketQueue));
q->mutex = SDL_CreateMutex(); q->mutex = SDL_CreateMutex();
q->cond = SDL_CreateCond(); q->cond = SDL_CreateCond();
packet_queue_put(q, &flush_pkt); q->abort_request = 1;
} }
static void packet_queue_flush(PacketQueue *q) static void packet_queue_flush(PacketQueue *q)
...@@ -361,7 +373,7 @@ static void packet_queue_flush(PacketQueue *q) ...@@ -361,7 +373,7 @@ static void packet_queue_flush(PacketQueue *q)
SDL_UnlockMutex(q->mutex); SDL_UnlockMutex(q->mutex);
} }
static void packet_queue_end(PacketQueue *q) static void packet_queue_destroy(PacketQueue *q)
{ {
packet_queue_flush(q); packet_queue_flush(q);
SDL_DestroyMutex(q->mutex); SDL_DestroyMutex(q->mutex);
...@@ -379,6 +391,14 @@ static void packet_queue_abort(PacketQueue *q) ...@@ -379,6 +391,14 @@ static void packet_queue_abort(PacketQueue *q)
SDL_UnlockMutex(q->mutex); 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. */ /* return < 0 if aborted, 0 if no packet and > 0 if packet. */
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
{ {
...@@ -877,6 +897,9 @@ static void stream_close(VideoState *is) ...@@ -877,6 +897,9 @@ static void stream_close(VideoState *is)
is->abort_request = 1; is->abort_request = 1;
SDL_WaitThread(is->read_tid, NULL); SDL_WaitThread(is->read_tid, NULL);
SDL_WaitThread(is->refresh_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 */ /* free all pictures */
for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) { for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
...@@ -1816,8 +1839,13 @@ static int video_thread(void *arg) ...@@ -1816,8 +1839,13 @@ static int video_thread(void *arg)
int last_w = is->video_st->codec->width; int last_w = is->video_st->codec->width;
int last_h = is->video_st->codec->height; 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; goto the_end;
}
filt_out = is->out_video_filter; filt_out = is->out_video_filter;
#endif #endif
...@@ -1893,6 +1921,7 @@ static int video_thread(void *arg) ...@@ -1893,6 +1921,7 @@ static int video_thread(void *arg)
stream_toggle_pause(is); stream_toggle_pause(is);
} }
the_end: the_end:
avcodec_flush_buffers(is->video_st->codec);
#if CONFIG_AVFILTER #if CONFIG_AVFILTER
av_freep(&vfilters); av_freep(&vfilters);
avfilter_graph_free(&graph); avfilter_graph_free(&graph);
...@@ -2240,9 +2269,9 @@ static int stream_component_open(VideoState *is, int stream_index) ...@@ -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]); opts = filter_codec_opts(codec_opts, codec, ic, ic->streams[stream_index]);
switch(avctx->codec_type){ 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_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: if(subtitle_codec_name) codec= avcodec_find_decoder_by_name(subtitle_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 : if(video_codec_name ) codec= avcodec_find_decoder_by_name( video_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) if (!codec)
return -1; return -1;
...@@ -2343,20 +2372,20 @@ static int stream_component_open(VideoState *is, int stream_index) ...@@ -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; is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / wanted_spec.freq;
memset(&is->audio_pkt, 0, sizeof(is->audio_pkt)); memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
packet_queue_init(&is->audioq); packet_queue_start(&is->audioq);
SDL_PauseAudio(0); SDL_PauseAudio(0);
break; break;
case AVMEDIA_TYPE_VIDEO: case AVMEDIA_TYPE_VIDEO:
is->video_stream = stream_index; is->video_stream = stream_index;
is->video_st = ic->streams[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); is->video_tid = SDL_CreateThread(video_thread, is);
break; break;
case AVMEDIA_TYPE_SUBTITLE: case AVMEDIA_TYPE_SUBTITLE:
is->subtitle_stream = stream_index; is->subtitle_stream = stream_index;
is->subtitle_st = ic->streams[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); is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
break; break;
...@@ -2381,7 +2410,7 @@ static void stream_component_close(VideoState *is, int stream_index) ...@@ -2381,7 +2410,7 @@ static void stream_component_close(VideoState *is, int stream_index)
SDL_CloseAudio(); SDL_CloseAudio();
packet_queue_end(&is->audioq); packet_queue_flush(&is->audioq);
av_free_packet(&is->audio_pkt); av_free_packet(&is->audio_pkt);
if (is->swr_ctx) if (is->swr_ctx)
swr_free(&is->swr_ctx); swr_free(&is->swr_ctx);
...@@ -2407,7 +2436,7 @@ static void stream_component_close(VideoState *is, int stream_index) ...@@ -2407,7 +2436,7 @@ static void stream_component_close(VideoState *is, int stream_index)
SDL_WaitThread(is->video_tid, NULL); SDL_WaitThread(is->video_tid, NULL);
packet_queue_end(&is->videoq); packet_queue_flush(&is->videoq);
break; break;
case AVMEDIA_TYPE_SUBTITLE: case AVMEDIA_TYPE_SUBTITLE:
packet_queue_abort(&is->subtitleq); packet_queue_abort(&is->subtitleq);
...@@ -2422,7 +2451,7 @@ static void stream_component_close(VideoState *is, int stream_index) ...@@ -2422,7 +2451,7 @@ static void stream_component_close(VideoState *is, int stream_index)
SDL_WaitThread(is->subtitle_tid, NULL); SDL_WaitThread(is->subtitle_tid, NULL);
packet_queue_end(&is->subtitleq); packet_queue_flush(&is->subtitleq);
break; break;
default: default:
break; break;
...@@ -2469,9 +2498,9 @@ static int read_thread(void *arg) ...@@ -2469,9 +2498,9 @@ static int read_thread(void *arg)
int orig_nb_streams; int orig_nb_streams;
memset(st_index, -1, sizeof(st_index)); memset(st_index, -1, sizeof(st_index));
is->video_stream = -1; is->last_video_stream = is->video_stream = -1;
is->audio_stream = -1; is->last_audio_stream = is->audio_stream = -1;
is->subtitle_stream = -1; is->last_subtitle_stream = is->subtitle_stream = -1;
ic = avformat_alloc_context(); ic = avformat_alloc_context();
ic->interrupt_callback.callback = decode_interrupt_cb; ic->interrupt_callback.callback = decode_interrupt_cb;
...@@ -2625,9 +2654,9 @@ static int read_thread(void *arg) ...@@ -2625,9 +2654,9 @@ static int read_thread(void *arg)
/* if the queue are full, no need to read more */ /* if the queue are full, no need to read more */
if ( is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE if ( is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
|| ( (is->audioq .nb_packets > MIN_FRAMES || is->audio_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 .nb_packets > MIN_FRAMES || is->video_stream < 0 || is->videoq.abort_request)
&& (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream < 0))) { && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream < 0 || is->subtitleq.abort_request))) {
/* wait 10 ms */ /* wait 10 ms */
SDL_Delay(10); SDL_Delay(10);
continue; continue;
...@@ -2732,6 +2761,10 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat) ...@@ -2732,6 +2761,10 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
is->subpq_mutex = SDL_CreateMutex(); is->subpq_mutex = SDL_CreateMutex();
is->subpq_cond = SDL_CreateCond(); 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->av_sync_type = av_sync_type;
is->read_tid = SDL_CreateThread(read_thread, is); is->read_tid = SDL_CreateThread(read_thread, is);
if (!is->read_tid) { if (!is->read_tid) {
...@@ -2745,16 +2778,19 @@ static void stream_cycle_channel(VideoState *is, int codec_type) ...@@ -2745,16 +2778,19 @@ static void stream_cycle_channel(VideoState *is, int codec_type)
{ {
AVFormatContext *ic = is->ic; AVFormatContext *ic = is->ic;
int start_index, stream_index; int start_index, stream_index;
int old_index;
AVStream *st; AVStream *st;
if (codec_type == AVMEDIA_TYPE_VIDEO) if (codec_type == AVMEDIA_TYPE_VIDEO) {
start_index = is->video_stream; start_index = is->last_video_stream;
else if (codec_type == AVMEDIA_TYPE_AUDIO) old_index = is->video_stream;
start_index = is->audio_stream; } else if (codec_type == AVMEDIA_TYPE_AUDIO) {
else start_index = is->last_audio_stream;
start_index = is->subtitle_stream; old_index = is->audio_stream;
if (start_index < (codec_type == AVMEDIA_TYPE_SUBTITLE ? -1 : 0)) } else {
return; start_index = is->last_subtitle_stream;
old_index = is->subtitle_stream;
}
stream_index = start_index; stream_index = start_index;
for (;;) { for (;;) {
if (++stream_index >= is->ic->nb_streams) if (++stream_index >= is->ic->nb_streams)
...@@ -2762,8 +2798,11 @@ static void stream_cycle_channel(VideoState *is, int codec_type) ...@@ -2762,8 +2798,11 @@ static void stream_cycle_channel(VideoState *is, int codec_type)
if (codec_type == AVMEDIA_TYPE_SUBTITLE) if (codec_type == AVMEDIA_TYPE_SUBTITLE)
{ {
stream_index = -1; stream_index = -1;
is->last_subtitle_stream = -1;
goto the_end; goto the_end;
} else }
if (start_index == -1)
return;
stream_index = 0; stream_index = 0;
} }
if (stream_index == start_index) if (stream_index == start_index)
...@@ -2786,7 +2825,7 @@ static void stream_cycle_channel(VideoState *is, int codec_type) ...@@ -2786,7 +2825,7 @@ static void stream_cycle_channel(VideoState *is, int codec_type)
} }
} }
the_end: the_end:
stream_component_close(is, start_index); stream_component_close(is, old_index);
stream_component_open(is, stream_index); stream_component_open(is, stream_index);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment