/*
- * FFplay : Simple Media Player based on the FFmpeg libraries
+ * ffplay : Simple Media Player based on the FFmpeg libraries
* Copyright (c) 2003 Fabrice Bellard
*
* This file is part of FFmpeg.
#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
#include <unistd.h>
#include <assert.h>
-const char program_name[] = "FFplay";
+const char program_name[] = "ffplay";
const int program_birth_year = 2003;
//#define DEBUG
};
typedef struct VideoState {
- SDL_Thread *parse_tid;
+ SDL_Thread *read_tid;
SDL_Thread *video_tid;
SDL_Thread *refresh_tid;
AVInputFormat *iformat;
enum AVSampleFormat audio_src_fmt;
AVAudioConvert *reformat_ctx;
- enum {
- SHOW_MODE_VIDEO = 0, SHOW_MODE_WAVES, SHOW_MODE_RDFT, SHOW_MODE_NB
+ enum ShowMode {
+ SHOW_MODE_NONE = -1, 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;
struct SwsContext *img_convert_ctx;
#endif
- // QETimer *video_timer;
char filename[1024];
int width, height, xleft, ytop;
static int exit_on_mousedown;
static int loop=1;
static int framedrop=1;
-static int show_mode = SHOW_MODE_VIDEO;
+static enum ShowMode show_mode = SHOW_MODE_NONE;
static int rdftspeed=20;
#if CONFIG_AVFILTER
vp = &is->pictq[is->pictq_rindex];
if (vp->bmp) {
#if CONFIG_AVFILTER
- if (vp->picref->video->pixel_aspect.num == 0)
+ if (vp->picref->video->sample_aspect_ratio.num == 0)
aspect_ratio = 0;
else
- aspect_ratio = av_q2d(vp->picref->video->pixel_aspect);
+ aspect_ratio = av_q2d(vp->picref->video->sample_aspect_ratio);
#else
/* XXX: use variable in the frame */
}
rect.x = is->xleft + x;
rect.y = is->ytop + y;
- rect.w = width;
- rect.h = height;
+ rect.w = FFMAX(width, 1);
+ rect.h = FFMAX(height, 1);
SDL_DisplayYUVOverlay(vp->bmp, &rect);
} else {
#if 0
}
/* pause or resume the video */
-static void stream_pause(VideoState *is)
+static void stream_toggle_pause(VideoState *is)
{
if (is->paused) {
is->frame_timer += av_gettime() / 1000000.0 + is->video_current_pts_drift - is->video_current_pts;
}
/* called to display each frame */
-static void video_refresh_timer(void *opaque)
+static void video_refresh(void *opaque)
{
VideoState *is = opaque;
VideoPicture *vp;
int i;
/* XXX: use a special url_shutdown call to abort parse cleanly */
is->abort_request = 1;
- SDL_WaitThread(is->parse_tid, NULL);
+ SDL_WaitThread(is->read_tid, NULL);
SDL_WaitThread(is->refresh_tid, NULL);
/* free all pictures */
SDL_UnlockMutex(is->pictq_mutex);
}
-/**
- *
- * @param pts the dts of the pkt / pts of the frame and guessed if not known
- */
-static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t pos)
+static int queue_picture(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos)
{
VideoPicture *vp;
+ double frame_delay, pts = pts1;
+
+ /* compute the exact PTS for the picture if it is omitted in the stream
+ * pts1 is the dts of the pkt / pts of the frame */
+ if (pts != 0) {
+ /* update video clock with pts, if present */
+ is->video_clock = pts;
+ } else {
+ pts = is->video_clock;
+ }
+ /* update video clock for next frame */
+ frame_delay = av_q2d(is->video_st->codec->time_base);
+ /* for MPEG2, the frame can be repeated, so we update the
+ clock accordingly */
+ frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
+ is->video_clock += frame_delay;
+
+#if defined(DEBUG_SYNC) && 0
+ printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
+ av_get_picture_type_char(src_frame->pict_type), pts, pts1);
+#endif
/* wait until we have space to put a new picture */
SDL_LockMutex(is->pictq_mutex);
return 0;
}
-/**
- * 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_picture(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos)
-{
- double frame_delay, pts;
-
- pts = pts1;
-
- if (pts != 0) {
- /* update video clock with pts, if present */
- is->video_clock = pts;
- } else {
- pts = is->video_clock;
- }
- /* update video clock for next frame */
- frame_delay = av_q2d(is->video_st->codec->time_base);
- /* for MPEG2, the frame can be repeated, so we update the
- clock accordingly */
- frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
- is->video_clock += frame_delay;
-
-#if defined(DEBUG_SYNC) && 0
- printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
- av_get_pict_type_char(src_frame->pict_type), pts, pts1);
-#endif
- return queue_picture(is, src_frame, pts, pos);
-}
-
static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacket *pkt)
{
int len1, got_picture, i;
av_free_packet(&pkt);
picref->pts = pts;
- picref->pos = pkt.pos;
- picref->video->pixel_aspect = priv->is->video_st->codec->sample_aspect_ratio;
+ picref->pos = priv->frame->pkt_pos;
+ picref->video->sample_aspect_ratio = priv->frame->sample_aspect_ratio;
avfilter_start_frame(link, picref);
avfilter_draw_slice(link, 0, link->h, 1);
avfilter_end_frame(link);
{
VideoState *is = arg;
AVFrame *frame= avcodec_alloc_frame();
- int64_t pts_int;
+ int64_t pts_int, pos;
double pts;
int ret;
#if CONFIG_AVFILTER
AVFilterGraph *graph = avfilter_graph_alloc();
AVFilterContext *filt_out = NULL;
- int64_t pos;
if ((ret = configure_video_filters(graph, is, vfilters)) < 0)
goto the_end;
}
#else
ret = get_video_frame(is, frame, &pts_int, &pkt);
+ pos = pkt.pos;
#endif
if (ret < 0) goto the_end;
pts = pts_int*av_q2d(is->video_st->time_base);
-#if CONFIG_AVFILTER
- ret = output_picture(is, frame, pts, pos);
-#else
- ret = output_picture(is, frame, pts, pkt.pos);
+ ret = queue_picture(is, frame, pts, pos);
+#if !CONFIG_AVFILTER
av_free_packet(&pkt);
#endif
if (ret < 0)
if (step)
if (cur_stream)
- stream_pause(cur_stream);
+ stream_toggle_pause(cur_stream);
}
the_end:
#if CONFIG_AVFILTER
av_free_packet(pkt);
// if (step)
// if (cur_stream)
-// stream_pause(cur_stream);
+// stream_toggle_pause(cur_stream);
}
the_end:
return 0;
}
/* this thread gets the stream from the disk or the network */
-static int decode_thread(void *arg)
+static int read_thread(void *arg)
{
VideoState *is = arg;
AVFormatContext *ic;
ap->height= frame_height;
ap->time_base= (AVRational){1, 25};
ap->pix_fmt = frame_pix_fmt;
+ ic->flags |= AVFMT_FLAG_PRIV_OPT;
- set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM, NULL);
err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
+ if (err >= 0) {
+ set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM, NULL);
+ err = av_demuxer_open(ic, ap);
+ if(err < 0){
+ avformat_free_context(ic);
+ ic= NULL;
+ }
+ }
if (err < 0) {
print_error(is->filename, err);
ret = -1;
ret= stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
}
is->refresh_tid = SDL_CreateThread(refresh_thread, is);
- if(ret<0) {
- if (!display_disable)
- is->show_mode = SHOW_MODE_RDFT;
- }
+ if (is->show_mode == SHOW_MODE_NONE)
+ is->show_mode = ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
stream_component_open(is, st_index[AVMEDIA_TYPE_SUBTITLE]);
is->subpq_cond = SDL_CreateCond();
is->av_sync_type = av_sync_type;
- is->parse_tid = SDL_CreateThread(decode_thread, is);
- if (!is->parse_tid) {
+ is->read_tid = SDL_CreateThread(read_thread, is);
+ if (!is->read_tid) {
av_free(is);
return NULL;
}
static void toggle_pause(void)
{
if (cur_stream)
- stream_pause(cur_stream);
+ stream_toggle_pause(cur_stream);
step = 0;
}
if (cur_stream) {
/* if the stream is paused unpause it, then step */
if (cur_stream->paused)
- stream_pause(cur_stream);
+ stream_toggle_pause(cur_stream);
}
step = 1;
}
alloc_picture(event.user.data1);
break;
case FF_REFRESH_EVENT:
- video_refresh_timer(event.user.data1);
+ video_refresh(event.user.data1);
cur_stream->refresh=0;
break;
default: