X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffplay.c;h=8140dd9645010f794d24267543f3131eeb3a0bf9;hb=80c5dc56104d96eae2d3170720bf5aa4f90467e4;hp=72ec35dbf4d480045280219ab9e2fa2935cc7fe1;hpb=0b4fc4bacd866b14b74bcfb1656a1f469da6ad46;p=ffmpeg diff --git a/ffplay.c b/ffplay.c index 72ec35dbf4d..8140dd96450 100644 --- a/ffplay.c +++ b/ffplay.c @@ -191,12 +191,11 @@ typedef struct Decoder { AVRational start_pts_tb; int64_t next_pts; AVRational next_pts_tb; + SDL_Thread *decoder_tid; } Decoder; typedef struct VideoState { SDL_Thread *read_tid; - SDL_Thread *video_tid; - SDL_Thread *audio_tid; AVInputFormat *iformat; int abort_request; int force_refresh; @@ -264,7 +263,6 @@ typedef struct VideoState { int xpos; double last_vis_time; - SDL_Thread *subtitle_tid; int subtitle_stream; AVStream *subtitle_st; PacketQueue subtitleq; @@ -280,6 +278,7 @@ typedef struct VideoState { struct SwsContext *img_convert_ctx; #endif SDL_Rect last_display_rect; + int eof; char filename[1024]; int width, height, xleft, ytop; @@ -768,6 +767,15 @@ static int64_t frame_queue_last_pos(FrameQueue *f) return -1; } +static void decoder_abort(Decoder *d, FrameQueue *fq) +{ + packet_queue_abort(d->queue); + frame_queue_signal(fq); + SDL_WaitThread(d->decoder_tid, NULL); + d->decoder_tid = NULL; + packet_queue_flush(d->queue); +} + static inline void fill_rectangle(SDL_Surface *screen, int x, int y, int w, int h, int color, int update) { @@ -1494,7 +1502,7 @@ static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_by static void stream_toggle_pause(VideoState *is) { if (is->paused) { - is->frame_timer += av_gettime_relative() / 1000000.0 + is->vidclk.pts_drift - is->vidclk.pts; + is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated; if (is->read_pause_return != AVERROR(ENOSYS)) { is->vidclk.paused = 0; } @@ -2196,6 +2204,12 @@ static int audio_thread(void *arg) return ret; } +static void decoder_start(Decoder *d, int (*fn)(void *), void *arg) +{ + packet_queue_start(d->queue); + d->decoder_tid = SDL_CreateThread(fn, arg); +} + static int video_thread(void *arg) { VideoState *is = arg; @@ -2216,6 +2230,9 @@ static int video_thread(void *arg) int last_vfilter_idx = 0; #endif + if (!frame) + return AVERROR(ENOMEM); + for (;;) { ret = get_video_frame(is, frame); if (ret < 0) @@ -2687,6 +2704,7 @@ static int stream_component_open(VideoState *is, int stream_index) goto fail; } + is->eof = 0; ic->streams[stream_index]->discard = AVDISCARD_DEFAULT; switch (avctx->codec_type) { case AVMEDIA_TYPE_AUDIO: @@ -2729,31 +2747,28 @@ static int stream_component_open(VideoState *is, int stream_index) is->audio_stream = stream_index; is->audio_st = ic->streams[stream_index]; - packet_queue_start(&is->audioq); decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread); if ((is->ic->iformat->flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK)) && !is->ic->iformat->read_seek) { is->auddec.start_pts = is->audio_st->start_time; is->auddec.start_pts_tb = is->audio_st->time_base; } - is->audio_tid = SDL_CreateThread(audio_thread, is); + decoder_start(&is->auddec, audio_thread, is); SDL_PauseAudio(0); break; case AVMEDIA_TYPE_VIDEO: is->video_stream = stream_index; is->video_st = ic->streams[stream_index]; - packet_queue_start(&is->videoq); decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread); - is->video_tid = SDL_CreateThread(video_thread, is); + decoder_start(&is->viddec, video_thread, is); is->queue_attachments_req = 1; break; case AVMEDIA_TYPE_SUBTITLE: is->subtitle_stream = stream_index; is->subtitle_st = ic->streams[stream_index]; - packet_queue_start(&is->subtitleq); decoder_init(&is->subdec, avctx, &is->subtitleq, is->continue_read_thread); - is->subtitle_tid = SDL_CreateThread(subtitle_thread, is); + decoder_start(&is->subdec, subtitle_thread, is); break; default: break; @@ -2776,13 +2791,9 @@ static void stream_component_close(VideoState *is, int stream_index) switch (avctx->codec_type) { case AVMEDIA_TYPE_AUDIO: - packet_queue_abort(&is->audioq); - frame_queue_signal(&is->sampq); + decoder_abort(&is->auddec, &is->sampq); SDL_CloseAudio(); - SDL_WaitThread(is->audio_tid, NULL); - decoder_destroy(&is->auddec); - packet_queue_flush(&is->audioq); swr_free(&is->swr_ctx); av_freep(&is->audio_buf1); is->audio_buf1_size = 0; @@ -2796,28 +2807,12 @@ static void stream_component_close(VideoState *is, int stream_index) } break; case AVMEDIA_TYPE_VIDEO: - packet_queue_abort(&is->videoq); - - /* note: we also signal this mutex to make sure we deblock the - video thread in all cases */ - frame_queue_signal(&is->pictq); - - SDL_WaitThread(is->video_tid, NULL); - + decoder_abort(&is->viddec, &is->pictq); decoder_destroy(&is->viddec); - packet_queue_flush(&is->videoq); break; case AVMEDIA_TYPE_SUBTITLE: - packet_queue_abort(&is->subtitleq); - - /* note: we also signal this mutex to make sure we deblock the - video thread in all cases */ - frame_queue_signal(&is->subpq); - - SDL_WaitThread(is->subtitle_tid, NULL); - + decoder_abort(&is->subdec, &is->subpq); decoder_destroy(&is->subdec); - packet_queue_flush(&is->subtitleq); break; default: break; @@ -2873,7 +2868,6 @@ static int read_thread(void *arg) int err, i, ret; int st_index[AVMEDIA_TYPE_NB]; AVPacket pkt1, *pkt = &pkt1; - int eof = 0; int64_t stream_start_time; int pkt_in_play_range = 0; AVDictionaryEntry *t; @@ -2881,13 +2875,20 @@ static int read_thread(void *arg) int orig_nb_streams; SDL_mutex *wait_mutex = SDL_CreateMutex(); int scan_all_pmts_set = 0; + int64_t pkt_ts; memset(st_index, -1, sizeof(st_index)); is->last_video_stream = is->video_stream = -1; is->last_audio_stream = is->audio_stream = -1; is->last_subtitle_stream = is->subtitle_stream = -1; + is->eof = 0; ic = avformat_alloc_context(); + if (!ic) { + av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n"); + ret = AVERROR(ENOMEM); + goto fail; + } ic->interrupt_callback.callback = decode_interrupt_cb; ic->interrupt_callback.opaque = is; if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) { @@ -3083,7 +3084,7 @@ static int read_thread(void *arg) } is->seek_req = 0; is->queue_attachments_req = 1; - eof = 0; + is->eof = 0; if (is->paused) step_to_next_frame(is); } @@ -3123,14 +3124,14 @@ static int read_thread(void *arg) } ret = av_read_frame(ic, pkt); if (ret < 0) { - if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !eof) { + if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) { if (is->video_stream >= 0) packet_queue_put_nullpacket(&is->videoq, is->video_stream); if (is->audio_stream >= 0) packet_queue_put_nullpacket(&is->audioq, is->audio_stream); if (is->subtitle_stream >= 0) packet_queue_put_nullpacket(&is->subtitleq, is->subtitle_stream); - eof = 1; + is->eof = 1; } if (ic->pb && ic->pb->error) break; @@ -3139,12 +3140,13 @@ static int read_thread(void *arg) SDL_UnlockMutex(wait_mutex); continue; } else { - eof = 0; + is->eof = 0; } /* check if packet is in play range specified by user, then queue, otherwise discard */ stream_start_time = ic->streams[pkt->stream_index]->start_time; + pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts; pkt_in_play_range = duration == AV_NOPTS_VALUE || - (pkt->pts - (stream_start_time != AV_NOPTS_VALUE ? stream_start_time : 0)) * + (pkt_ts - (stream_start_time != AV_NOPTS_VALUE ? stream_start_time : 0)) * av_q2d(ic->streams[pkt->stream_index]->time_base) - (double)(start_time != AV_NOPTS_VALUE ? start_time : 0) / 1000000 <= ((double)duration / 1000000);