X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffplay.c;h=5eb5a21165f7a8275f85ce6282c8ce10fdc278a2;hb=7d132c544b2447ef5a6b04ca6f21e245d6a48986;hp=413225e9ceb9e54e367bbba9746581f304d2279c;hpb=4ed29207c2d2a72a6943d85cf58b5fc50cc2adec;p=ffmpeg diff --git a/ffplay.c b/ffplay.c index 413225e9ceb..5eb5a21165f 100644 --- a/ffplay.c +++ b/ffplay.c @@ -19,14 +19,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" #include #include #include "libavutil/avstring.h" #include "libavformat/avformat.h" -#include "libavformat/rtsp.h" #include "libavdevice/avdevice.h" #include "libswscale/swscale.h" #include "libavcodec/audioconvert.h" +#include "libavcodec/colorspace.h" #include "libavcodec/opt.h" #include "cmdutils.h" @@ -46,7 +47,7 @@ const int program_birth_year = 2003; //#define DEBUG_SYNC #define MAX_VIDEOQ_SIZE (5 * 256 * 1024) -#define MAX_AUDIOQ_SIZE (5 * 16 * 1024) +#define MAX_AUDIOQ_SIZE (20 * 16 * 1024) #define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024) /* SDL audio buffer size, in samples. Should be small to have precise @@ -135,9 +136,8 @@ typedef struct VideoState { uint8_t *audio_buf; unsigned int audio_buf_size; /* in bytes */ int audio_buf_index; /* in bytes */ + AVPacket audio_pkt_temp; AVPacket audio_pkt; - uint8_t *audio_pkt_data; - int audio_pkt_size; enum SampleFormat audio_src_fmt; AVAudioConvert *reformat_ctx; @@ -169,6 +169,7 @@ typedef struct VideoState { int pictq_size, pictq_rindex, pictq_windex; SDL_mutex *pictq_mutex; SDL_cond *pictq_cond; + struct SwsContext *img_convert_ctx; // QETimer *video_timer; char filename[1024]; @@ -195,7 +196,7 @@ static int wanted_video_stream= 0; static int wanted_subtitle_stream= -1; static int seek_by_bytes; static int display_disable; -static int show_status; +static int show_status = 1; static int av_sync_type = AV_SYNC_AUDIO_MASTER; static int64_t start_time = AV_NOPTS_VALUE; static int debug = 0; @@ -387,24 +388,6 @@ void fill_border(VideoState *s, int x, int y, int w, int h, int color) } #endif - - -#define SCALEBITS 10 -#define ONE_HALF (1 << (SCALEBITS - 1)) -#define FIX(x) ((int) ((x) * (1<> SCALEBITS) - -#define RGB_TO_U_CCIR(r1, g1, b1, shift)\ -(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \ - FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) - -#define RGB_TO_V_CCIR(r1, g1, b1, shift)\ -(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \ - FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) - #define ALPHA_BLEND(a, oldp, newp, s)\ ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s)) @@ -1156,7 +1139,7 @@ static void video_refresh_timer(void *opaque) double av_diff; cur_time = av_gettime(); - if (!last_time || (cur_time - last_time) >= 500 * 1000) { + if (!last_time || (cur_time - last_time) >= 30000) { aqsize = 0; vqsize = 0; sqsize = 0; @@ -1189,23 +1172,6 @@ static void alloc_picture(void *opaque) if (vp->bmp) SDL_FreeYUVOverlay(vp->bmp); -#if 0 - /* XXX: use generic function */ - /* XXX: disable overlay if no hardware acceleration or if RGB format */ - switch(is->video_st->codec->pix_fmt) { - case PIX_FMT_YUV420P: - case PIX_FMT_YUV422P: - case PIX_FMT_YUV444P: - case PIX_FMT_YUYV422: - case PIX_FMT_YUV410P: - case PIX_FMT_YUV411P: - is_yuv = 1; - break; - default: - is_yuv = 0; - break; - } -#endif vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width, is->video_st->codec->height, SDL_YV12_OVERLAY, @@ -1227,8 +1193,6 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts) { VideoPicture *vp; int dst_pix_fmt; - AVPicture pict; - static struct SwsContext *img_convert_ctx; /* wait until we have space to put a new picture */ SDL_LockMutex(is->pictq_mutex); @@ -1270,10 +1234,13 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts) /* if the frame is not skipped, then display it */ if (vp->bmp) { + AVPicture pict; + /* get a pointer on the bitmap */ SDL_LockYUVOverlay (vp->bmp); dst_pix_fmt = PIX_FMT_YUV420P; + memset(&pict,0,sizeof(AVPicture)); pict.data[0] = vp->bmp->pixels[0]; pict.data[1] = vp->bmp->pixels[2]; pict.data[2] = vp->bmp->pixels[1]; @@ -1282,16 +1249,16 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts) pict.linesize[1] = vp->bmp->pitches[2]; pict.linesize[2] = vp->bmp->pitches[1]; sws_flags = av_get_int(sws_opts, "sws_flags", NULL); - img_convert_ctx = sws_getCachedContext(img_convert_ctx, + is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx, is->video_st->codec->width, is->video_st->codec->height, is->video_st->codec->pix_fmt, is->video_st->codec->width, is->video_st->codec->height, dst_pix_fmt, sws_flags, NULL, NULL, NULL); - if (img_convert_ctx == NULL) { + if (is->img_convert_ctx == NULL) { fprintf(stderr, "Cannot initialize the conversion context\n"); exit(1); } - sws_scale(img_convert_ctx, src_frame->data, src_frame->linesize, + sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize, 0, is->video_st->codec->height, pict.data, pict.linesize); /* update the bitmap content */ SDL_UnlockYUVOverlay(vp->bmp); @@ -1370,9 +1337,9 @@ static int video_thread(void *arg) /* NOTE: ipts is the PTS of the _first_ picture beginning in this packet, if any */ is->video_st->codec->reordered_opaque= pkt->pts; - len1 = avcodec_decode_video(is->video_st->codec, + len1 = avcodec_decode_video2(is->video_st->codec, frame, &got_picture, - pkt->data, pkt->size); + pkt); if( (decoder_reorder_pts || pkt->dts == AV_NOPTS_VALUE) && frame->reordered_opaque != AV_NOPTS_VALUE) @@ -1438,9 +1405,9 @@ static int subtitle_thread(void *arg) if (pkt->pts != AV_NOPTS_VALUE) pts = av_q2d(is->subtitle_st->time_base)*pkt->pts; - len1 = avcodec_decode_subtitle(is->subtitle_st->codec, + len1 = avcodec_decode_subtitle2(is->subtitle_st->codec, &sp->sub, &got_subtitle, - pkt->data, pkt->size); + pkt); // if (len1 < 0) // break; if (got_subtitle && sp->sub.format == 0) { @@ -1575,6 +1542,7 @@ static int synchronize_audio(VideoState *is, short *samples, /* decode one audio frame and returns its uncompressed size */ static int audio_decode_frame(VideoState *is, double *pts_ptr) { + AVPacket *pkt_temp = &is->audio_pkt_temp; AVPacket *pkt = &is->audio_pkt; AVCodecContext *dec= is->audio_st->codec; int n, len1, data_size; @@ -1582,19 +1550,19 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) for(;;) { /* NOTE: the audio packet can contain several frames */ - while (is->audio_pkt_size > 0) { + while (pkt_temp->size > 0) { data_size = sizeof(is->audio_buf1); - len1 = avcodec_decode_audio2(dec, + len1 = avcodec_decode_audio3(dec, (int16_t *)is->audio_buf1, &data_size, - is->audio_pkt_data, is->audio_pkt_size); + pkt_temp); if (len1 < 0) { /* if error, we skip the frame */ - is->audio_pkt_size = 0; + pkt_temp->size = 0; break; } - is->audio_pkt_data += len1; - is->audio_pkt_size -= len1; + pkt_temp->data += len1; + pkt_temp->size -= len1; if (data_size <= 0) continue; @@ -1664,8 +1632,8 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) continue; } - is->audio_pkt_data = pkt->data; - is->audio_pkt_size = pkt->size; + pkt_temp->data = pkt->data; + pkt_temp->size = pkt->size; /* if update the audio clock with the pts */ if (pkt->pts != AV_NOPTS_VALUE) { @@ -1893,13 +1861,6 @@ static void stream_component_close(VideoState *is, int stream_index) } } -static void dump_stream_info(const AVFormatContext *s) -{ - AVMetadataTag *tag = NULL; - while ((tag=av_metadata_get(s->metadata,"",tag,AV_METADATA_IGNORE_SUFFIX))) - fprintf(stderr, "%s: %s\n", tag->key, tag->value); -} - /* since we have only one decoding thread, we can use a global variable instead of a thread local variable */ static VideoState *global_video_state; @@ -1917,6 +1878,7 @@ static int decode_thread(void *arg) int err, i, ret, video_index, audio_index, subtitle_index; AVPacket pkt1, *pkt = &pkt1; AVFormatParameters params, *ap = ¶ms; + int eof=0; video_index = -1; audio_index = -1; @@ -1992,7 +1954,6 @@ static int decode_thread(void *arg) } if (show_status) { dump_format(ic, 0, is->filename, 0); - dump_stream_info(ic); } /* open the streams */ @@ -2060,6 +2021,7 @@ static int decode_thread(void *arg) } } is->seek_req = 0; + eof= 0; } /* if the queue are full, no need to read more */ @@ -2070,21 +2032,25 @@ static int decode_thread(void *arg) SDL_Delay(10); continue; } - if(url_feof(ic->pb)) { - av_init_packet(pkt); - pkt->data=NULL; - pkt->size=0; - pkt->stream_index= is->video_stream; - packet_queue_put(&is->videoq, pkt); + if(url_feof(ic->pb) || eof) { + if(is->video_stream >= 0){ + av_init_packet(pkt); + pkt->data=NULL; + pkt->size=0; + pkt->stream_index= is->video_stream; + packet_queue_put(&is->videoq, pkt); + } + SDL_Delay(10); continue; } ret = av_read_frame(ic, pkt); if (ret < 0) { - if (ret != AVERROR_EOF && url_ferror(ic->pb) == 0) { - SDL_Delay(100); /* wait for user event */ - continue; - } else + if (ret == AVERROR_EOF) + eof=1; + if (url_ferror(ic->pb)) break; + SDL_Delay(100); /* wait for user event */ + continue; } if (pkt->stream_index == is->audio_stream) { packet_queue_put(&is->audioq, pkt); @@ -2180,6 +2146,9 @@ static void stream_close(VideoState *is) SDL_DestroyCond(is->pictq_cond); SDL_DestroyMutex(is->subpq_mutex); SDL_DestroyCond(is->subpq_cond); + if (is->img_convert_ctx) + sws_freeContext(is->img_convert_ctx); + av_free(is); } static void stream_cycle_channel(VideoState *is, int codec_type) @@ -2261,10 +2230,15 @@ static void step_to_next_frame(void) static void do_exit(void) { + int i; if (cur_stream) { stream_close(cur_stream); cur_stream = NULL; } + for (i = 0; i < CODEC_TYPE_NB; i++) + av_free(avcodec_opts[i]); + av_free(avformat_opts); + av_free(sws_opts); if (show_status) printf("\n"); SDL_Quit(); @@ -2352,6 +2326,7 @@ static void event_loop(void) break; case SDL_MOUSEBUTTONDOWN: if (cur_stream) { + int64_t ts; int ns, hh, mm, ss; int tns, thh, tmm, tss; tns = cur_stream->ic->duration/1000000LL; @@ -2365,7 +2340,10 @@ static void event_loop(void) ss = (ns%60); fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100, hh, mm, ss, thh, tmm, tss); - stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0); + ts = frac*cur_stream->ic->duration; + if (cur_stream->ic->start_time != AV_NOPTS_VALUE) + ts += cur_stream->ic->start_time; + stream_seek(cur_stream, ts, 0); } break; case SDL_VIDEORESIZE: @@ -2475,10 +2453,7 @@ static int opt_thread_count(const char *opt, const char *arg) } static const OptionDef options[] = { - { "h", OPT_EXIT, {(void*)show_help}, "show help" }, - { "version", OPT_EXIT, {(void*)show_version}, "show version" }, - { "L", OPT_EXIT, {(void*)show_license}, "show license" }, - { "formats", OPT_EXIT, {(void*)show_formats}, "show available formats, codecs, protocols, ..." }, +#include "cmdutils_common_opts.h" { "x", HAS_ARG | OPT_FUNC2, {(void*)opt_width}, "force displayed width", "width" }, { "y", HAS_ARG | OPT_FUNC2, {(void*)opt_height}, "force displayed height", "height" }, { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },