X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffplay.c;h=eb5b2789664be282e368d8b221cf17438903c076;hb=8772156be0725fd20d948a855616fe155fafdc09;hp=2e50920b9fddf8be67d852912af92dacb4623784;hpb=76ad67cae751658ce2d84e83b38a4d673e9e85a3;p=ffmpeg diff --git a/ffplay.c b/ffplay.c index 2e50920b9fd..eb5b2789664 100644 --- a/ffplay.c +++ b/ffplay.c @@ -28,14 +28,15 @@ #include "libavutil/avstring.h" #include "libavutil/colorspace.h" #include "libavutil/pixdesc.h" -#include "libavcore/imgutils.h" -#include "libavcore/parseutils.h" -#include "libavcore/samplefmt.h" +#include "libavutil/imgutils.h" +#include "libavutil/parseutils.h" +#include "libavutil/samplefmt.h" +#include "libavutil/avassert.h" #include "libavformat/avformat.h" #include "libavdevice/avdevice.h" #include "libswscale/swscale.h" #include "libavcodec/audioconvert.h" -#include "libavcodec/opt.h" +#include "libavutil/opt.h" #include "libavcodec/avfft.h" #if CONFIG_AVFILTER @@ -139,7 +140,6 @@ typedef struct VideoState { int64_t seek_rel; int read_pause_return; AVFormatContext *ic; - int dtg_active_format; int audio_stream; @@ -167,7 +167,9 @@ typedef struct VideoState { enum AVSampleFormat audio_src_fmt; AVAudioConvert *reformat_ctx; - int show_audio; /* if true, display audio samples */ + enum { + SHOW_MODE_VIDEO = 0, SHOW_MODE_WAVES, SHOW_MODE_RDFT, SHOW_MODE_NB + } show_mode; int16_t sample_array[SAMPLE_ARRAY_SIZE]; int sample_array_index; int last_i_start; @@ -218,7 +220,6 @@ typedef struct VideoState { } VideoState; static void show_help(void); -static int audio_write_get_buf_size(VideoState *is); /* options specified by the user */ static AVInputFormat *file_iformat; @@ -264,6 +265,7 @@ static int exit_on_keydown; static int exit_on_mousedown; static int loop=1; static int framedrop=1; +static int show_mode = SHOW_MODE_VIDEO; static int rdftspeed=20; #if CONFIG_AVFILTER @@ -283,7 +285,37 @@ static AVPacket flush_pkt; static SDL_Surface *screen; -static int packet_queue_put(PacketQueue *q, AVPacket *pkt); +static int packet_queue_put(PacketQueue *q, AVPacket *pkt) +{ + AVPacketList *pkt1; + + /* duplicate the packet */ + if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0) + return -1; + + pkt1 = av_malloc(sizeof(AVPacketList)); + if (!pkt1) + return -1; + pkt1->pkt = *pkt; + pkt1->next = NULL; + + + SDL_LockMutex(q->mutex); + + if (!q->last_pkt) + + q->first_pkt = pkt1; + else + q->last_pkt->next = pkt1; + q->last_pkt = pkt1; + q->nb_packets++; + q->size += pkt1->pkt.size + sizeof(*pkt1); + /* XXX: should duplicate packet data in DV case */ + SDL_CondSignal(q->cond); + + SDL_UnlockMutex(q->mutex); + return 0; +} /* packet queue handling */ static void packet_queue_init(PacketQueue *q) @@ -318,38 +350,6 @@ static void packet_queue_end(PacketQueue *q) SDL_DestroyCond(q->cond); } -static int packet_queue_put(PacketQueue *q, AVPacket *pkt) -{ - AVPacketList *pkt1; - - /* duplicate the packet */ - if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0) - return -1; - - pkt1 = av_malloc(sizeof(AVPacketList)); - if (!pkt1) - return -1; - pkt1->pkt = *pkt; - pkt1->next = NULL; - - - SDL_LockMutex(q->mutex); - - if (!q->last_pkt) - - q->first_pkt = pkt1; - else - q->last_pkt->next = pkt1; - q->last_pkt = pkt1; - q->nb_packets++; - q->size += pkt1->pkt.size + sizeof(*pkt1); - /* XXX: should duplicate packet data in DV case */ - SDL_CondSignal(q->cond); - - SDL_UnlockMutex(q->mutex); - return 0; -} - static void packet_queue_abort(PacketQueue *q) { SDL_LockMutex(q->mutex); @@ -710,49 +710,12 @@ static void video_image_display(VideoState *is) if (aspect_ratio <= 0.0) aspect_ratio = 1.0; aspect_ratio *= (float)vp->width / (float)vp->height; - /* if an active format is indicated, then it overrides the - mpeg format */ -#if 0 - if (is->video_st->codec->dtg_active_format != is->dtg_active_format) { - is->dtg_active_format = is->video_st->codec->dtg_active_format; - printf("dtg_active_format=%d\n", is->dtg_active_format); - } -#endif -#if 0 - switch(is->video_st->codec->dtg_active_format) { - case FF_DTG_AFD_SAME: - default: - /* nothing to do */ - break; - case FF_DTG_AFD_4_3: - aspect_ratio = 4.0 / 3.0; - break; - case FF_DTG_AFD_16_9: - aspect_ratio = 16.0 / 9.0; - break; - case FF_DTG_AFD_14_9: - aspect_ratio = 14.0 / 9.0; - break; - case FF_DTG_AFD_4_3_SP_14_9: - aspect_ratio = 14.0 / 9.0; - break; - case FF_DTG_AFD_16_9_SP_14_9: - aspect_ratio = 14.0 / 9.0; - break; - case FF_DTG_AFD_SP_4_3: - aspect_ratio = 4.0 / 3.0; - break; - } -#endif - if (is->subtitle_st) - { - if (is->subpq_size > 0) - { + if (is->subtitle_st) { + if (is->subpq_size > 0) { sp = &is->subpq[is->subpq_rindex]; - if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) - { + if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) { SDL_LockYUVOverlay (vp->bmp); pict.data[0] = vp->bmp->pixels[0]; @@ -802,13 +765,16 @@ static void video_image_display(VideoState *is) } } +/* get the current audio output buffer size, in samples. With SDL, we + cannot have a precise information */ +static int audio_write_get_buf_size(VideoState *is) +{ + return is->audio_buf_size - is->audio_buf_index; +} + static inline int compute_mod(int a, int b) { - a = a % b; - if (a >= 0) - return a; - else - return a + b; + return a < 0 ? a%b + b : a%b; } static void video_audio_display(VideoState *s) @@ -826,7 +792,7 @@ static void video_audio_display(VideoState *s) channels = s->audio_st->codec->channels; nb_display_channels = channels; if (!s->paused) { - int data_used= s->show_audio==1 ? s->width : (2*nb_freq); + int data_used= s->show_mode == SHOW_MODE_WAVES ? s->width : (2*nb_freq); n = 2 * channels; delay = audio_write_get_buf_size(s); delay /= n; @@ -843,7 +809,7 @@ static void video_audio_display(VideoState *s) delay = data_used; i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE); - if(s->show_audio==1){ + if (s->show_mode == SHOW_MODE_WAVES) { h= INT_MIN; for(i=0; i<1000; i+=channels){ int idx= (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE; @@ -865,7 +831,7 @@ static void video_audio_display(VideoState *s) } bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00); - if(s->show_audio==1){ + if (s->show_mode == SHOW_MODE_WAVES) { fill_rectangle(screen, s->xleft, s->ytop, s->width, s->height, bgcolor); @@ -1005,7 +971,7 @@ static void video_display(VideoState *is) { if(!screen) video_open(cur_stream); - if (is->audio_st && is->show_audio) + if (is->audio_st && is->show_mode != SHOW_MODE_VIDEO) video_audio_display(is); else if (is->video_st) video_image_display(is); @@ -1022,7 +988,8 @@ static int refresh_thread(void *opaque) is->refresh=1; SDL_PushEvent(&event); } - usleep(is->audio_st && is->show_audio ? rdftspeed*1000 : 5000); //FIXME ideally we should wait the correct time but SDLs event passing is so slow it would be silly + //FIXME ideally we should wait the correct time but SDLs event passing is so slow it would be silly + usleep(is->audio_st && is->show_mode != SHOW_MODE_VIDEO ? rdftspeed*1000 : 5000); } return 0; } @@ -1284,7 +1251,14 @@ retry: if (is->audio_st && is->video_st) av_diff = get_audio_clock(is) - get_video_clock(is); printf("%7.2f A-V:%7.3f s:%3.1f aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r", - get_master_clock(is), av_diff, FFMAX(is->skip_frames-1, 0), aqsize / 1024, vqsize / 1024, sqsize, is->video_st->codec->pts_correction_num_faulty_dts, is->video_st->codec->pts_correction_num_faulty_pts); + get_master_clock(is), + av_diff, + FFMAX(is->skip_frames-1, 0), + aqsize / 1024, + vqsize / 1024, + sqsize, + is->video_st ? is->video_st->codec->pts_correction_num_faulty_dts : 0, + is->video_st ? is->video_st->codec->pts_correction_num_faulty_pts : 0); fflush(stdout); last_time = cur_time; } @@ -1393,10 +1367,7 @@ static void alloc_picture(void *opaque) static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t pos) { VideoPicture *vp; - int dst_pix_fmt; -#if CONFIG_AVFILTER - AVPicture pict_src; -#endif + /* wait until we have space to put a new picture */ SDL_LockMutex(is->pictq_mutex); @@ -1456,7 +1427,6 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t /* 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]; @@ -1467,22 +1437,14 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t pict.linesize[2] = vp->bmp->pitches[1]; #if CONFIG_AVFILTER - pict_src.data[0] = src_frame->data[0]; - pict_src.data[1] = src_frame->data[1]; - pict_src.data[2] = src_frame->data[2]; - - pict_src.linesize[0] = src_frame->linesize[0]; - pict_src.linesize[1] = src_frame->linesize[1]; - pict_src.linesize[2] = src_frame->linesize[2]; - //FIXME use direct rendering - av_picture_copy(&pict, &pict_src, + av_picture_copy(&pict, (AVPicture *)src_frame, vp->pix_fmt, vp->width, vp->height); #else sws_flags = av_get_int(sws_opts, "sws_flags", NULL); is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx, vp->width, vp->height, vp->pix_fmt, vp->width, vp->height, - dst_pix_fmt, sws_flags, NULL, NULL, NULL); + PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL); if (is->img_convert_ctx == NULL) { fprintf(stderr, "Cannot initialize the conversion context\n"); exit(1); @@ -1512,7 +1474,7 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t * compute the exact PTS for the picture if it is omitted in the stream * @param pts1 the dts of the pkt / pts of the frame */ -static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos) +static int output_picture(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos) { double frame_delay, pts; @@ -1608,6 +1570,9 @@ static int input_get_buffer(AVCodecContext *codec, AVFrame *pic) int perms = AV_PERM_WRITE; int i, w, h, stride[4]; unsigned edge; + int pixel_size; + + av_assert0(codec->flags & CODEC_FLAG_EMU_EDGE); if (codec->codec->capabilities & CODEC_CAP_NEG_LINESIZES) perms |= AV_PERM_NEG_LINESIZES; @@ -1621,6 +1586,10 @@ static int input_get_buffer(AVCodecContext *codec, AVFrame *pic) w = codec->width; h = codec->height; + + if(av_image_check_size(w, h, 0, codec)) + return -1; + avcodec_align_dimensions2(codec, &w, &h, stride); edge = codec->flags & CODEC_FLAG_EMU_EDGE ? 0 : avcodec_get_edge_width(); w += edge << 1; @@ -1629,6 +1598,7 @@ static int input_get_buffer(AVCodecContext *codec, AVFrame *pic) if(!(ref = avfilter_get_video_buffer(ctx->outputs[0], perms, w, h))) return -1; + pixel_size = av_pix_fmt_descriptors[ref->format].comp[0].step_minus1+1; ref->video->w = codec->width; ref->video->h = codec->height; for(i = 0; i < 4; i ++) { @@ -1636,7 +1606,7 @@ static int input_get_buffer(AVCodecContext *codec, AVFrame *pic) unsigned vshift = (i == 1 || i == 2) ? av_pix_fmt_descriptors[ref->format].log2_chroma_h : 0; if (ref->data[i]) { - ref->data[i] += (edge >> hshift) + ((edge * ref->linesize[i]) >> vshift); + ref->data[i] += ((edge * pixel_size) >> hshift) + ((edge * ref->linesize[i]) >> vshift); } pic->data[i] = ref->data[i]; pic->linesize[i] = ref->linesize[i]; @@ -1686,11 +1656,14 @@ static int input_init(AVFilterContext *ctx, const char *args, void *opaque) priv->is = opaque; codec = priv->is->video_st->codec; codec->opaque = ctx; - if(codec->codec->capabilities & CODEC_CAP_DR1) { + if((codec->codec->capabilities & CODEC_CAP_DR1) + ) { + codec->flags |= CODEC_FLAG_EMU_EDGE; priv->use_dr1 = 1; codec->get_buffer = input_get_buffer; codec->release_buffer = input_release_buffer; codec->reget_buffer = input_reget_buffer; + codec->thread_safe_callbacks = 1; } priv->frame = avcodec_alloc_frame(); @@ -1882,9 +1855,9 @@ static int video_thread(void *arg) pts = pts_int*av_q2d(is->video_st->time_base); #if CONFIG_AVFILTER - ret = output_picture2(is, frame, pts, pos); + ret = output_picture(is, frame, pts, pos); #else - ret = output_picture2(is, frame, pts, pkt.pos); + ret = output_picture(is, frame, pts, pkt.pos); av_free_packet(&pkt); #endif if (ret < 0) @@ -2178,14 +2151,6 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) } } -/* get the current audio output buffer size, in samples. With SDL, we - cannot have a precise information */ -static int audio_write_get_buf_size(VideoState *is) -{ - return is->audio_buf_size - is->audio_buf_index; -} - - /* prepare a new audio buffer */ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) { @@ -2204,7 +2169,7 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) is->audio_buf_size = 1024; memset(is->audio_buf, 0, is->audio_buf_size); } else { - if (is->show_audio) + if (is->show_mode != SHOW_MODE_VIDEO) update_sample_display(is, (int16_t *)is->audio_buf, audio_size); audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size, pts); @@ -2256,7 +2221,7 @@ static int stream_component_open(VideoState *is, int stream_index) avctx->skip_loop_filter= skip_loop_filter; avctx->error_recognition= error_recognition; avctx->error_concealment= error_concealment; - avcodec_thread_init(avctx, thread_count); + avctx->thread_count= thread_count; set_context_opts(avctx, avcodec_opts[avctx->codec_type], 0, codec); @@ -2423,7 +2388,7 @@ static int decode_thread(void *arg) is->subtitle_stream = -1; global_video_state = is; - url_set_interrupt_cb(decode_interrupt_cb); + avio_set_interrupt_cb(decode_interrupt_cb); memset(ap, 0, sizeof(*ap)); @@ -2494,9 +2459,11 @@ static int decode_thread(void *arg) st_index[AVMEDIA_TYPE_VIDEO]), NULL, 0); if (show_status) { - dump_format(ic, 0, is->filename, 0); + av_dump_format(ic, 0, is->filename, 0); } + is->show_mode = show_mode; + /* open the streams */ if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) { stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]); @@ -2509,7 +2476,7 @@ static int decode_thread(void *arg) is->refresh_tid = SDL_CreateThread(refresh_thread, is); if(ret<0) { if (!display_disable) - is->show_audio = 2; + is->show_mode = SHOW_MODE_RDFT; } if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) { @@ -2594,13 +2561,14 @@ static int decode_thread(void *arg) goto fail; } } + eof=0; continue; } ret = av_read_frame(ic, pkt); if (ret < 0) { if (ret == AVERROR_EOF || url_feof(ic->pb)) eof=1; - if (url_ferror(ic->pb)) + if (ic->pb && ic->pb->error) break; SDL_Delay(100); /* wait for user event */ continue; @@ -2642,7 +2610,7 @@ static int decode_thread(void *arg) av_close_input_file(is->ic); is->ic = NULL; /* safety */ } - url_set_interrupt_cb(NULL); + avio_set_interrupt_cb(NULL); if (ret != 0) { SDL_Event event; @@ -2763,7 +2731,7 @@ static void toggle_audio_display(void) { if (cur_stream) { int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00); - cur_stream->show_audio = (cur_stream->show_audio + 1) % 3; + cur_stream->show_mode = (cur_stream->show_mode + 1) % SHOW_MODE_NB; fill_rectangle(screen, cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height, bgcolor); @@ -2835,7 +2803,7 @@ static void event_loop(void) }else if(cur_stream->audio_stream >= 0 && cur_stream->audio_pkt.pos>=0){ pos= cur_stream->audio_pkt.pos; }else - pos = url_ftell(cur_stream->ic->pb); + pos = avio_tell(cur_stream->ic->pb); if (cur_stream->ic->bit_rate) incr *= cur_stream->ic->bit_rate / 8.0; else @@ -2868,7 +2836,7 @@ static void event_loop(void) } if (cur_stream) { if(seek_by_bytes || cur_stream->ic->duration<=0){ - uint64_t size= url_fsize(cur_stream->ic->pb); + uint64_t size= avio_size(cur_stream->ic->pb); stream_seek(cur_stream, size*x/cur_stream->width, 0, 1); }else{ int64_t ts; @@ -3005,6 +2973,15 @@ static int opt_thread_count(const char *opt, const char *arg) return 0; } +static int opt_show_mode(const char *opt, const char *arg) +{ + show_mode = !strcmp(arg, "video") ? SHOW_MODE_VIDEO : + !strcmp(arg, "waves") ? SHOW_MODE_WAVES : + !strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT : + parse_number_or_die(opt, arg, OPT_INT, 0, SHOW_MODE_NB-1); + return 0; +} + static const OptionDef options[] = { #include "cmdutils_common_opts.h" { "x", HAS_ARG | OPT_FUNC2, {(void*)opt_width}, "force displayed width", "width" }, @@ -3048,7 +3025,9 @@ static const OptionDef options[] = { { "vf", OPT_STRING | HAS_ARG, {(void*)&vfilters}, "video filters", "filter list" }, #endif { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, {(void*)&rdftspeed}, "rdft speed", "msecs" }, + { "showmode", HAS_ARG | OPT_FUNC2, {(void*)opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" }, { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" }, + { "i", OPT_DUMMY, {NULL}, "ffmpeg compatibility dummy option", ""}, { NULL, }, };