#include <inttypes.h>
#include <math.h>
#include <limits.h>
+#include <stdint.h>
+
#include "libavutil/avstring.h"
#include "libavutil/colorspace.h"
#include "libavutil/mathematics.h"
#include "libavutil/dict.h"
#include "libavutil/parseutils.h"
#include "libavutil/samplefmt.h"
+#include "libavutil/time.h"
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
#if CONFIG_AVFILTER
# include "libavfilter/avfilter.h"
-# include "libavfilter/avfiltergraph.h"
+# include "libavfilter/buffersink.h"
+# include "libavfilter/buffersrc.h"
#endif
#include "cmdutils.h"
#undef main /* We don't want SDL to override our main() */
#endif
-#include <unistd.h>
#include <assert.h>
const char program_name[] = "avplay";
/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
#define SAMPLE_ARRAY_SIZE (2 * 65536)
-static int sws_flags = SWS_BICUBIC;
+static int64_t sws_flags = SWS_BICUBIC;
typedef struct PacketQueue {
AVPacketList *first_pkt, *last_pkt;
#define SUBPICTURE_QUEUE_SIZE 4
typedef struct VideoPicture {
- double pts; ///< presentation time stamp for this picture
- double target_clock; ///< av_gettime() time at which this should be displayed ideally
- int64_t pos; ///< byte position in file
+ double pts; // presentation timestamp for this picture
+ double target_clock; // av_gettime() time at which this should be displayed ideally
+ int64_t pos; // byte position in file
SDL_Overlay *bmp;
int width, height; /* source height & width */
int allocated;
int reallocate;
- enum PixelFormat pix_fmt;
+ enum AVPixelFormat pix_fmt;
-#if CONFIG_AVFILTER
- AVFilterBufferRef *picref;
-#endif
+ AVRational sar;
} VideoPicture;
typedef struct SubPicture {
enum AVSampleFormat sdl_sample_fmt;
uint64_t sdl_channel_layout;
int sdl_channels;
+ int sdl_sample_rate;
enum AVSampleFormat resample_sample_fmt;
uint64_t resample_channel_layout;
+ int resample_sample_rate;
AVAudioResampleContext *avr;
AVFrame *frame;
double frame_timer;
double frame_last_pts;
double frame_last_delay;
- double video_clock; ///< pts of last decoded frame / predicted pts of next decoded frame
+ double video_clock; // pts of last decoded frame / predicted pts of next decoded frame
int video_stream;
AVStream *video_st;
PacketQueue videoq;
- double video_current_pts; ///< current displayed pts (different from video_clock if frame fifos are used)
- double video_current_pts_drift; ///< video_current_pts - time (av_gettime) at which we updated video_current_pts - used to have running video pts
- int64_t video_current_pos; ///< current displayed file pos
+ double video_current_pts; // current displayed pts (different from video_clock if frame fifos are used)
+ double video_current_pts_drift; // video_current_pts - time (av_gettime) at which we updated video_current_pts - used to have running video pts
+ int64_t video_current_pos; // current displayed file pos
VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
int pictq_size, pictq_rindex, pictq_windex;
SDL_mutex *pictq_mutex;
PtsCorrectionContext pts_ctx;
#if CONFIG_AVFILTER
- AVFilterContext *out_video_filter; ///< the last filter in the video chain
+ AVFilterContext *in_video_filter; // the first filter in the video chain
+ AVFilterContext *out_video_filter; // the last filter in the video chain
#endif
float skip_frames;
int refresh;
} VideoState;
-static void show_help(void);
-
/* options specified by the user */
static AVInputFormat *file_iformat;
static const char *input_filename;
static int av_sync_type = AV_SYNC_AUDIO_MASTER;
static int64_t start_time = AV_NOPTS_VALUE;
static int64_t duration = AV_NOPTS_VALUE;
-static int debug = 0;
-static int debug_mv = 0;
static int step = 0;
static int workaround_bugs = 1;
static int fast = 0;
static int exit_on_mousedown;
static int loop = 1;
static int framedrop = 1;
+static int infinite_buffer = 0;
static int rdftspeed = 20;
#if CONFIG_AVFILTER
static SDL_Surface *screen;
-void exit_program(int ret)
-{
- exit(ret);
-}
-
static int packet_queue_put(PacketQueue *q, AVPacket *pkt);
/* packet queue handling */
vp = &is->pictq[is->pictq_rindex];
if (vp->bmp) {
#if CONFIG_AVFILTER
- if (vp->picref->video->pixel_aspect.num == 0)
+ if (!vp->sar.num)
aspect_ratio = 0;
else
- aspect_ratio = av_q2d(vp->picref->video->pixel_aspect);
+ aspect_ratio = av_q2d(vp->sar);
#else
/* XXX: use variable in the frame */
the last buffer computation */
if (audio_callback_time) {
time_diff = av_gettime() - audio_callback_time;
- delay -= (time_diff * s->audio_st->codec->sample_rate) / 1000000;
+ delay -= (time_diff * s->sdl_sample_rate) / 1000000;
}
delay += 2 * data_used;
}
av_rdft_calc(s->rdft, data[ch]);
}
- // least efficient way to do this, we should of course directly access it but its more than fast enough
+ /* Least efficient way to do this, we should of course
+ * directly access it but it is more than fast enough. */
for (y = 0; y < s->height; y++) {
double w = 1 / sqrt(nb_freq);
int a = sqrt(w * sqrt(data[0][2 * y + 0] * data[0][2 * y + 0] + data[0][2 * y + 1] * data[0][2 * y + 1]));
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
+ av_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
}
return 0;
}
hw_buf_size = audio_write_get_buf_size(is);
bytes_per_sec = 0;
if (is->audio_st) {
- bytes_per_sec = is->audio_st->codec->sample_rate * is->sdl_channels *
+ bytes_per_sec = is->sdl_sample_rate * is->sdl_channels *
av_get_bytes_per_sample(is->sdl_sample_fmt);
}
if (bytes_per_sec)
/* free all pictures */
for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
vp = &is->pictq[i];
-#if CONFIG_AVFILTER
- if (vp->picref) {
- avfilter_unref_buffer(vp->picref);
- vp->picref = NULL;
- }
-#endif
if (vp->bmp) {
SDL_FreeYUVOverlay(vp->bmp);
vp->bmp = NULL;
cur_stream = NULL;
}
uninit_opts();
-#if CONFIG_AVFILTER
- avfilter_uninit();
-#endif
avformat_network_deinit();
if (show_status)
printf("\n");
SDL_FreeYUVOverlay(vp->bmp);
#if CONFIG_AVFILTER
- if (vp->picref)
- avfilter_unref_buffer(vp->picref);
- vp->picref = NULL;
-
vp->width = is->out_video_filter->inputs[0]->w;
vp->height = is->out_video_filter->inputs[0]->h;
vp->pix_fmt = is->out_video_filter->inputs[0]->format;
SDL_UnlockMutex(is->pictq_mutex);
}
-/**
- *
- * @param pts the dts of the pkt / pts of the frame and guessed if not known
- */
+/* The 'pts' parameter is the dts of the packet / pts of the frame and
+ * guessed if not known. */
static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t pos)
{
VideoPicture *vp;
#if CONFIG_AVFILTER
AVPicture pict_src;
#else
- int dst_pix_fmt = PIX_FMT_YUV420P;
+ int dst_pix_fmt = AV_PIX_FMT_YUV420P;
#endif
/* wait until we have space to put a new picture */
SDL_LockMutex(is->pictq_mutex);
/* if the frame is not skipped, then display it */
if (vp->bmp) {
AVPicture pict = { { 0 } };
-#if CONFIG_AVFILTER
- if (vp->picref)
- avfilter_unref_buffer(vp->picref);
- vp->picref = src_frame->opaque;
-#endif
/* get a pointer on the bitmap */
SDL_LockYUVOverlay (vp->bmp);
av_picture_copy(&pict, &pict_src,
vp->pix_fmt, vp->width, vp->height);
#else
- sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
+ av_opt_get_int(sws_opts, "sws_flags", 0, &sws_flags);
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);
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
- */
+/* Compute the exact PTS for the picture if it is omitted in the stream.
+ * The 'pts1' parameter is the dts of the packet / pts of the frame. */
static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos)
{
double frame_delay, pts;
+ int ret;
pts = pts1;
frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
is->video_clock += frame_delay;
- return queue_picture(is, src_frame, pts, pos);
+ ret = queue_picture(is, src_frame, pts, pos);
+ av_frame_unref(src_frame);
+ return ret;
}
static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacket *pkt)
if (*pts == AV_NOPTS_VALUE) {
*pts = 0;
}
+ if (is->video_st->sample_aspect_ratio.num) {
+ frame->sample_aspect_ratio = is->video_st->sample_aspect_ratio;
+ }
is->skip_frames_index += 1;
if (is->skip_frames_index >= is->skip_frames) {
is->skip_frames_index -= FFMAX(is->skip_frames, 1.0);
return 1;
}
-
+ av_frame_unref(frame);
}
return 0;
}
#if CONFIG_AVFILTER
-typedef struct {
- VideoState *is;
- AVFrame *frame;
- int use_dr1;
-} FilterPriv;
-
-static int input_get_buffer(AVCodecContext *codec, AVFrame *pic)
-{
- AVFilterContext *ctx = codec->opaque;
- AVFilterBufferRef *ref;
- int perms = AV_PERM_WRITE;
- int i, w, h, stride[AV_NUM_DATA_POINTERS];
- unsigned edge;
- int pixel_size;
-
- if (codec->codec->capabilities & CODEC_CAP_NEG_LINESIZES)
- perms |= AV_PERM_NEG_LINESIZES;
-
- if (pic->buffer_hints & FF_BUFFER_HINTS_VALID) {
- if (pic->buffer_hints & FF_BUFFER_HINTS_READABLE) perms |= AV_PERM_READ;
- if (pic->buffer_hints & FF_BUFFER_HINTS_PRESERVE) perms |= AV_PERM_PRESERVE;
- if (pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE) perms |= AV_PERM_REUSE2;
- }
- if (pic->reference) perms |= AV_PERM_READ | AV_PERM_PRESERVE;
-
- w = codec->width;
- h = codec->height;
- avcodec_align_dimensions2(codec, &w, &h, stride);
- edge = codec->flags & CODEC_FLAG_EMU_EDGE ? 0 : avcodec_get_edge_width();
- w += edge << 1;
- h += edge << 1;
-
- 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 ++) {
- unsigned hshift = (i == 1 || i == 2) ? av_pix_fmt_descriptors[ref->format].log2_chroma_w : 0;
- unsigned vshift = (i == 1 || i == 2) ? av_pix_fmt_descriptors[ref->format].log2_chroma_h : 0;
-
- if (ref->data[i]) {
- ref->data[i] += ((edge * pixel_size) >> hshift) + ((edge * ref->linesize[i]) >> vshift);
- }
- pic->data[i] = ref->data[i];
- pic->linesize[i] = ref->linesize[i];
- }
- pic->opaque = ref;
- pic->type = FF_BUFFER_TYPE_USER;
- pic->reordered_opaque = codec->reordered_opaque;
- pic->width = codec->width;
- pic->height = codec->height;
- pic->format = codec->pix_fmt;
- pic->sample_aspect_ratio = codec->sample_aspect_ratio;
- if (codec->pkt) pic->pkt_pts = codec->pkt->pts;
- else pic->pkt_pts = AV_NOPTS_VALUE;
- return 0;
-}
-
-static void input_release_buffer(AVCodecContext *codec, AVFrame *pic)
-{
- memset(pic->data, 0, sizeof(pic->data));
- avfilter_unref_buffer(pic->opaque);
-}
-
-static int input_reget_buffer(AVCodecContext *codec, AVFrame *pic)
-{
- AVFilterBufferRef *ref = pic->opaque;
-
- if (pic->data[0] == NULL) {
- pic->buffer_hints |= FF_BUFFER_HINTS_READABLE;
- return codec->get_buffer(codec, pic);
- }
-
- if ((codec->width != ref->video->w) || (codec->height != ref->video->h) ||
- (codec->pix_fmt != ref->format)) {
- av_log(codec, AV_LOG_ERROR, "Picture properties changed.\n");
- return -1;
- }
-
- pic->reordered_opaque = codec->reordered_opaque;
- if (codec->pkt) pic->pkt_pts = codec->pkt->pts;
- else pic->pkt_pts = AV_NOPTS_VALUE;
- return 0;
-}
-
-static int input_init(AVFilterContext *ctx, const char *args, void *opaque)
-{
- FilterPriv *priv = ctx->priv;
- AVCodecContext *codec;
- if (!opaque) return -1;
-
- priv->is = opaque;
- codec = priv->is->video_st->codec;
- codec->opaque = ctx;
- if (codec->codec->capabilities & CODEC_CAP_DR1) {
- 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();
-
- return 0;
-}
-
-static void input_uninit(AVFilterContext *ctx)
-{
- FilterPriv *priv = ctx->priv;
- av_free(priv->frame);
-}
-
-static int input_request_frame(AVFilterLink *link)
+static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters)
{
- FilterPriv *priv = link->src->priv;
- AVFilterBufferRef *picref;
- int64_t pts = 0;
- AVPacket pkt;
+ char sws_flags_str[128];
+ char buffersrc_args[256];
int ret;
+ AVFilterContext *filt_src = NULL, *filt_out = NULL, *filt_format;
+ AVCodecContext *codec = is->video_st->codec;
- while (!(ret = get_video_frame(priv->is, priv->frame, &pts, &pkt)))
- av_free_packet(&pkt);
- if (ret < 0)
- return -1;
-
- if (priv->use_dr1) {
- picref = avfilter_ref_buffer(priv->frame->opaque, ~0);
- } else {
- picref = avfilter_get_video_buffer(link, AV_PERM_WRITE, link->w, link->h);
- av_image_copy(picref->data, picref->linesize,
- priv->frame->data, priv->frame->linesize,
- picref->format, link->w, link->h);
- }
- av_free_packet(&pkt);
-
- avfilter_copy_frame_props(picref, priv->frame);
- picref->pts = pts;
-
- avfilter_start_frame(link, picref);
- avfilter_draw_slice(link, 0, link->h, 1);
- avfilter_end_frame(link);
-
- return 0;
-}
-
-static int input_query_formats(AVFilterContext *ctx)
-{
- FilterPriv *priv = ctx->priv;
- enum PixelFormat pix_fmts[] = {
- priv->is->video_st->codec->pix_fmt, PIX_FMT_NONE
- };
-
- avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
- return 0;
-}
-
-static int input_config_props(AVFilterLink *link)
-{
- FilterPriv *priv = link->src->priv;
- AVCodecContext *c = priv->is->video_st->codec;
-
- link->w = c->width;
- link->h = c->height;
- link->time_base = priv->is->video_st->time_base;
-
- return 0;
-}
-
-static AVFilter input_filter =
-{
- .name = "avplay_input",
-
- .priv_size = sizeof(FilterPriv),
+ snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%"PRId64, sws_flags);
+ graph->scale_sws_opts = av_strdup(sws_flags_str);
- .init = input_init,
- .uninit = input_uninit,
+ snprintf(buffersrc_args, sizeof(buffersrc_args), "%d:%d:%d:%d:%d:%d:%d",
+ codec->width, codec->height, codec->pix_fmt,
+ is->video_st->time_base.num, is->video_st->time_base.den,
+ codec->sample_aspect_ratio.num, codec->sample_aspect_ratio.den);
- .query_formats = input_query_formats,
- .inputs = (AVFilterPad[]) {{ .name = NULL }},
- .outputs = (AVFilterPad[]) {{ .name = "default",
- .type = AVMEDIA_TYPE_VIDEO,
- .request_frame = input_request_frame,
- .config_props = input_config_props, },
- { .name = NULL }},
-};
-
-static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters)
-{
- static const enum PixelFormat pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
- char sws_flags_str[128];
- int ret;
- SinkContext sink_ctx = { .pix_fmts = pix_fmts };
- AVFilterContext *filt_src = NULL, *filt_out = NULL;
- snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%d", sws_flags);
- graph->scale_sws_opts = av_strdup(sws_flags_str);
+ if ((ret = avfilter_graph_create_filter(&filt_src,
+ avfilter_get_by_name("buffer"),
+ "src", buffersrc_args, NULL,
+ graph)) < 0)
+ return ret;
+ if ((ret = avfilter_graph_create_filter(&filt_out,
+ avfilter_get_by_name("buffersink"),
+ "out", NULL, NULL, graph)) < 0)
+ return ret;
- if ((ret = avfilter_graph_create_filter(&filt_src, &input_filter, "src",
- NULL, is, graph)) < 0)
+ if ((ret = avfilter_graph_create_filter(&filt_format,
+ avfilter_get_by_name("format"),
+ "format", "yuv420p", NULL, graph)) < 0)
return ret;
- if ((ret = avfilter_graph_create_filter(&filt_out, &sink, "out",
- NULL, &sink_ctx, graph)) < 0)
+ if ((ret = avfilter_link(filt_format, 0, filt_out, 0)) < 0)
return ret;
+
if (vfilters) {
AVFilterInOut *outputs = avfilter_inout_alloc();
AVFilterInOut *inputs = avfilter_inout_alloc();
outputs->next = NULL;
inputs->name = av_strdup("out");
- inputs->filter_ctx = filt_out;
+ inputs->filter_ctx = filt_format;
inputs->pad_idx = 0;
inputs->next = NULL;
if ((ret = avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL)) < 0)
return ret;
} else {
- if ((ret = avfilter_link(filt_src, 0, filt_out, 0)) < 0)
+ if ((ret = avfilter_link(filt_src, 0, filt_format, 0)) < 0)
return ret;
}
if ((ret = avfilter_graph_config(graph, NULL)) < 0)
return ret;
+ is->in_video_filter = filt_src;
is->out_video_filter = filt_out;
return ret;
static int video_thread(void *arg)
{
+ AVPacket pkt = { 0 };
VideoState *is = arg;
- AVFrame *frame = avcodec_alloc_frame();
+ AVFrame *frame = av_frame_alloc();
int64_t pts_int;
double pts;
int ret;
#if CONFIG_AVFILTER
AVFilterGraph *graph = avfilter_graph_alloc();
- AVFilterContext *filt_out = NULL;
- int64_t pos;
+ AVFilterContext *filt_out = NULL, *filt_in = NULL;
int last_w = is->video_st->codec->width;
int last_h = is->video_st->codec->height;
if ((ret = configure_video_filters(graph, is, vfilters)) < 0)
goto the_end;
+ filt_in = is->in_video_filter;
filt_out = is->out_video_filter;
#endif
for (;;) {
-#if !CONFIG_AVFILTER
- AVPacket pkt;
-#else
- AVFilterBufferRef *picref;
+#if CONFIG_AVFILTER
AVRational tb;
#endif
while (is->paused && !is->videoq.abort_request)
SDL_Delay(10);
+
+ av_free_packet(&pkt);
+
+ ret = get_video_frame(is, frame, &pts_int, &pkt);
+ if (ret < 0)
+ goto the_end;
+
+ if (!ret)
+ continue;
+
#if CONFIG_AVFILTER
if ( last_w != is->video_st->codec->width
|| last_h != is->video_st->codec->height) {
graph = avfilter_graph_alloc();
if ((ret = configure_video_filters(graph, is, vfilters)) < 0)
goto the_end;
+ filt_in = is->in_video_filter;
filt_out = is->out_video_filter;
last_w = is->video_st->codec->width;
last_h = is->video_st->codec->height;
}
- ret = get_filtered_video_frame(filt_out, frame, &picref, &tb);
- if (picref) {
- pts_int = picref->pts;
- pos = picref->pos;
- frame->opaque = picref;
- }
-
- if (ret >= 0 && av_cmp_q(tb, is->video_st->time_base)) {
- av_unused int64_t pts1 = pts_int;
- pts_int = av_rescale_q(pts_int, tb, is->video_st->time_base);
- av_dlog(NULL, "video_thread(): "
- "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n",
- tb.num, tb.den, pts1,
- is->video_st->time_base.num, is->video_st->time_base.den, pts_int);
- }
-#else
- ret = get_video_frame(is, frame, &pts_int, &pkt);
-#endif
+ frame->pts = pts_int;
+ ret = av_buffersrc_add_frame(filt_in, frame);
if (ret < 0)
goto the_end;
- if (!ret)
- continue;
-
- pts = pts_int * av_q2d(is->video_st->time_base);
+ while (ret >= 0) {
+ ret = av_buffersink_get_frame(filt_out, frame);
+ if (ret < 0) {
+ ret = 0;
+ break;
+ }
-#if CONFIG_AVFILTER
- ret = output_picture2(is, frame, pts, pos);
+ pts_int = frame->pts;
+ tb = filt_out->inputs[0]->time_base;
+ if (av_cmp_q(tb, is->video_st->time_base)) {
+ av_unused int64_t pts1 = pts_int;
+ pts_int = av_rescale_q(pts_int, tb, is->video_st->time_base);
+ av_dlog(NULL, "video_thread(): "
+ "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n",
+ tb.num, tb.den, pts1,
+ is->video_st->time_base.num, is->video_st->time_base.den, pts_int);
+ }
+ pts = pts_int * av_q2d(is->video_st->time_base);
+ ret = output_picture2(is, frame, pts, 0);
+ }
#else
+ pts = pts_int * av_q2d(is->video_st->time_base);
ret = output_picture2(is, frame, pts, pkt.pos);
- av_free_packet(&pkt);
#endif
+
if (ret < 0)
goto the_end;
+
if (step)
if (cur_stream)
stream_pause(cur_stream);
av_freep(&vfilters);
avfilter_graph_free(&graph);
#endif
- av_free(frame);
+ av_free_packet(&pkt);
+ av_frame_free(&frame);
return 0;
}
avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
if (fabs(avg_diff) >= is->audio_diff_threshold) {
- wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
+ wanted_size = samples_size + ((int)(diff * is->sdl_sample_rate) * n);
nb_samples = samples_size / n;
min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
int resample_changed, audio_resample;
if (!is->frame) {
- if (!(is->frame = avcodec_alloc_frame()))
+ if (!(is->frame = av_frame_alloc()))
return AVERROR(ENOMEM);
- } else
- avcodec_get_frame_defaults(is->frame);
+ }
if (flush_complete)
break;
}
data_size = av_samples_get_buffer_size(NULL, dec->channels,
is->frame->nb_samples,
- dec->sample_fmt, 1);
+ is->frame->format, 1);
- audio_resample = dec->sample_fmt != is->sdl_sample_fmt ||
- dec->channel_layout != is->sdl_channel_layout;
+ audio_resample = is->frame->format != is->sdl_sample_fmt ||
+ is->frame->channel_layout != is->sdl_channel_layout ||
+ is->frame->sample_rate != is->sdl_sample_rate;
- resample_changed = dec->sample_fmt != is->resample_sample_fmt ||
- dec->channel_layout != is->resample_channel_layout;
+ resample_changed = is->frame->format != is->resample_sample_fmt ||
+ is->frame->channel_layout != is->resample_channel_layout ||
+ is->frame->sample_rate != is->resample_sample_rate;
if ((!is->avr && audio_resample) || resample_changed) {
int ret;
}
}
if (audio_resample) {
- av_opt_set_int(is->avr, "in_channel_layout", dec->channel_layout, 0);
- av_opt_set_int(is->avr, "in_sample_fmt", dec->sample_fmt, 0);
- av_opt_set_int(is->avr, "in_sample_rate", dec->sample_rate, 0);
- av_opt_set_int(is->avr, "out_channel_layout", is->sdl_channel_layout, 0);
- av_opt_set_int(is->avr, "out_sample_fmt", is->sdl_sample_fmt, 0);
- av_opt_set_int(is->avr, "out_sample_rate", dec->sample_rate, 0);
- if (av_get_bytes_per_sample(dec->sample_fmt) <= 2)
- av_opt_set_int(is->avr, "internal_sample_fmt", AV_SAMPLE_FMT_S16P, 0);
+ av_opt_set_int(is->avr, "in_channel_layout", is->frame->channel_layout, 0);
+ av_opt_set_int(is->avr, "in_sample_fmt", is->frame->format, 0);
+ av_opt_set_int(is->avr, "in_sample_rate", is->frame->sample_rate, 0);
+ av_opt_set_int(is->avr, "out_channel_layout", is->sdl_channel_layout, 0);
+ av_opt_set_int(is->avr, "out_sample_fmt", is->sdl_sample_fmt, 0);
+ av_opt_set_int(is->avr, "out_sample_rate", is->sdl_sample_rate, 0);
if ((ret = avresample_open(is->avr)) < 0) {
fprintf(stderr, "error initializing libavresample\n");
break;
}
}
- is->resample_sample_fmt = dec->sample_fmt;
- is->resample_channel_layout = dec->channel_layout;
+ is->resample_sample_fmt = is->frame->format;
+ is->resample_channel_layout = is->frame->channel_layout;
+ is->resample_sample_rate = is->frame->sample_rate;
}
if (audio_resample) {
is->audio_buf1 = tmp_out;
out_samples = avresample_convert(is->avr,
- (void **)&is->audio_buf1,
+ &is->audio_buf1,
out_linesize, nb_samples,
- (void **)is->frame->data,
+ is->frame->data,
is->frame->linesize[0],
is->frame->nb_samples);
if (out_samples < 0) {
*pts_ptr = pts;
n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt);
is->audio_clock += (double)data_size /
- (double)(n * dec->sample_rate);
+ (double)(n * is->sdl_sample_rate);
#ifdef DEBUG
{
static double last_clock;
return -1;
avctx = ic->streams[stream_index]->codec;
- opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index]);
+ opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], NULL);
codec = avcodec_find_decoder(avctx->codec_id);
- avctx->debug_mv = debug_mv;
- avctx->debug = debug;
avctx->workaround_bugs = workaround_bugs;
avctx->idct_algo = idct;
avctx->skip_frame = skip_frame;
if (!av_dict_get(opts, "threads", NULL, 0))
av_dict_set(&opts, "threads", "auto", 0);
+ if (avctx->codec_type == AVMEDIA_TYPE_VIDEO)
+ av_dict_set(&opts, "refcounted_frames", "1", 0);
if (!codec ||
avcodec_open2(avctx, codec, &opts) < 0)
return -1;
/* prepare audio output */
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
- wanted_spec.freq = avctx->sample_rate;
- wanted_spec.format = AUDIO_S16SYS;
+ is->sdl_sample_rate = avctx->sample_rate;
if (!avctx->channel_layout)
avctx->channel_layout = av_get_default_channel_layout(avctx->channels);
is->sdl_channel_layout = AV_CH_LAYOUT_STEREO;
is->sdl_channels = av_get_channel_layout_nb_channels(is->sdl_channel_layout);
+ wanted_spec.format = AUDIO_S16SYS;
+ wanted_spec.freq = is->sdl_sample_rate;
wanted_spec.channels = is->sdl_channels;
wanted_spec.silence = 0;
wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
is->audio_hw_buf_size = spec.size;
is->sdl_sample_fmt = AV_SAMPLE_FMT_S16;
is->resample_sample_fmt = is->sdl_sample_fmt;
- is->resample_channel_layout = is->sdl_channel_layout;
+ is->resample_channel_layout = avctx->channel_layout;
+ is->resample_sample_rate = avctx->sample_rate;
}
ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
avresample_free(&is->avr);
av_freep(&is->audio_buf1);
is->audio_buf = NULL;
- av_freep(&is->frame);
+ av_frame_free(&is->frame);
if (is->rdft) {
av_rdft_end(is->rdft);
}
/* if the queue are full, no need to read more */
- if ( is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
+ if (!infinite_buffer &&
+ (is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
|| ( (is->audioq .size > MIN_AUDIOQ_SIZE || is->audio_stream < 0)
&& (is->videoq .nb_packets > MIN_FRAMES || is->video_stream < 0)
- && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream < 0))) {
+ && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream < 0)))) {
/* wait 10 ms */
SDL_Delay(10);
continue;
static void toggle_full_screen(void)
{
- is_full_screen = !is_full_screen;
#if defined(__APPLE__) && SDL_VERSION_ATLEAST(1, 2, 14)
/* OS X needs to empty the picture_queue */
- for (int i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
+ int i;
+ for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++)
cur_stream->pictq[i].reallocate = 1;
- }
#endif
+ is_full_screen = !is_full_screen;
video_open(cur_stream);
}
}
}
-static int opt_frame_size(const char *opt, const char *arg)
+static int opt_frame_size(void *optctx, const char *opt, const char *arg)
{
av_log(NULL, AV_LOG_ERROR,
"Option '%s' has been removed, use private format options instead\n", opt);
return AVERROR(EINVAL);
}
-static int opt_width(const char *opt, const char *arg)
+static int opt_width(void *optctx, const char *opt, const char *arg)
{
screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
return 0;
}
-static int opt_height(const char *opt, const char *arg)
+static int opt_height(void *optctx, const char *opt, const char *arg)
{
screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
return 0;
}
-static int opt_format(const char *opt, const char *arg)
+static int opt_format(void *optctx, const char *opt, const char *arg)
{
file_iformat = av_find_input_format(arg);
if (!file_iformat) {
return 0;
}
-static int opt_frame_pix_fmt(const char *opt, const char *arg)
+static int opt_frame_pix_fmt(void *optctx, const char *opt, const char *arg)
{
av_log(NULL, AV_LOG_ERROR,
"Option '%s' has been removed, use private format options instead\n", opt);
return AVERROR(EINVAL);
}
-static int opt_sync(const char *opt, const char *arg)
+static int opt_sync(void *optctx, const char *opt, const char *arg)
{
if (!strcmp(arg, "audio"))
av_sync_type = AV_SYNC_AUDIO_MASTER;
return 0;
}
-static int opt_seek(const char *opt, const char *arg)
+static int opt_seek(void *optctx, const char *opt, const char *arg)
{
start_time = parse_time_or_die(opt, arg, 1);
return 0;
}
-static int opt_duration(const char *opt, const char *arg)
+static int opt_duration(void *optctx, const char *opt, const char *arg)
{
duration = parse_time_or_die(opt, arg, 1);
return 0;
}
-static int opt_debug(const char *opt, const char *arg)
-{
- av_log_set_level(99);
- debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
- return 0;
-}
-
-static int opt_vismv(const char *opt, const char *arg)
-{
- debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
- return 0;
-}
-
static const OptionDef options[] = {
#include "cmdutils_common_opts.h"
- { "x", HAS_ARG, { (void*)opt_width }, "force displayed width", "width" },
- { "y", HAS_ARG, { (void*)opt_height }, "force displayed height", "height" },
- { "s", HAS_ARG | OPT_VIDEO, { (void*)opt_frame_size }, "set frame size (WxH or abbreviation)", "size" },
- { "fs", OPT_BOOL, { (void*)&is_full_screen }, "force full screen" },
- { "an", OPT_BOOL, { (void*)&audio_disable }, "disable audio" },
- { "vn", OPT_BOOL, { (void*)&video_disable }, "disable video" },
- { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&wanted_stream[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_number" },
- { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&wanted_stream[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_number" },
- { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&wanted_stream[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_number" },
- { "ss", HAS_ARG, { (void*)&opt_seek }, "seek to a given position in seconds", "pos" },
- { "t", HAS_ARG, { (void*)&opt_duration }, "play \"duration\" seconds of audio/video", "duration" },
- { "bytes", OPT_INT | HAS_ARG, { (void*)&seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" },
- { "nodisp", OPT_BOOL, { (void*)&display_disable }, "disable graphical display" },
- { "f", HAS_ARG, { (void*)opt_format }, "force format", "fmt" },
- { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { (void*)opt_frame_pix_fmt }, "set pixel format", "format" },
- { "stats", OPT_BOOL | OPT_EXPERT, { (void*)&show_status }, "show status", "" },
- { "debug", HAS_ARG | OPT_EXPERT, { (void*)opt_debug }, "print specific debug info", "" },
- { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&workaround_bugs }, "workaround bugs", "" },
- { "vismv", HAS_ARG | OPT_EXPERT, { (void*)opt_vismv }, "visualize motion vectors", "" },
- { "fast", OPT_BOOL | OPT_EXPERT, { (void*)&fast }, "non spec compliant optimizations", "" },
- { "genpts", OPT_BOOL | OPT_EXPERT, { (void*)&genpts }, "generate pts", "" },
- { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""},
- { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&skip_loop_filter }, "", "" },
- { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&skip_frame }, "", "" },
- { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&skip_idct }, "", "" },
- { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&idct }, "set idct algo", "algo" },
- { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&error_concealment }, "set error concealment options", "bit_mask" },
- { "sync", HAS_ARG | OPT_EXPERT, { (void*)opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" },
- { "autoexit", OPT_BOOL | OPT_EXPERT, { (void*)&autoexit }, "exit at the end", "" },
- { "exitonkeydown", OPT_BOOL | OPT_EXPERT, { (void*)&exit_on_keydown }, "exit on key down", "" },
- { "exitonmousedown", OPT_BOOL | OPT_EXPERT, { (void*)&exit_on_mousedown }, "exit on mouse down", "" },
- { "loop", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&loop }, "set number of times the playback shall be looped", "loop count" },
- { "framedrop", OPT_BOOL | OPT_EXPERT, { (void*)&framedrop }, "drop frames when cpu is too slow", "" },
- { "window_title", OPT_STRING | HAS_ARG, { (void*)&window_title }, "set window title", "window title" },
+ { "x", HAS_ARG, { .func_arg = opt_width }, "force displayed width", "width" },
+ { "y", HAS_ARG, { .func_arg = opt_height }, "force displayed height", "height" },
+ { "s", HAS_ARG | OPT_VIDEO, { .func_arg = opt_frame_size }, "set frame size (WxH or abbreviation)", "size" },
+ { "fs", OPT_BOOL, { &is_full_screen }, "force full screen" },
+ { "an", OPT_BOOL, { &audio_disable }, "disable audio" },
+ { "vn", OPT_BOOL, { &video_disable }, "disable video" },
+ { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_number" },
+ { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_number" },
+ { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_number" },
+ { "ss", HAS_ARG, { .func_arg = opt_seek }, "seek to a given position in seconds", "pos" },
+ { "t", HAS_ARG, { .func_arg = opt_duration }, "play \"duration\" seconds of audio/video", "duration" },
+ { "bytes", OPT_INT | HAS_ARG, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" },
+ { "nodisp", OPT_BOOL, { &display_disable }, "disable graphical display" },
+ { "f", HAS_ARG, { .func_arg = opt_format }, "force format", "fmt" },
+ { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_frame_pix_fmt }, "set pixel format", "format" },
+ { "stats", OPT_BOOL | OPT_EXPERT, { &show_status }, "show status", "" },
+ { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, { &workaround_bugs }, "workaround bugs", "" },
+ { "fast", OPT_BOOL | OPT_EXPERT, { &fast }, "non spec compliant optimizations", "" },
+ { "genpts", OPT_BOOL | OPT_EXPERT, { &genpts }, "generate pts", "" },
+ { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, { &decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""},
+ { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, { &skip_loop_filter }, "", "" },
+ { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, { &skip_frame }, "", "" },
+ { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, { &skip_idct }, "", "" },
+ { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, { &idct }, "set idct algo", "algo" },
+ { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, { &error_concealment }, "set error concealment options", "bit_mask" },
+ { "sync", HAS_ARG | OPT_EXPERT, { .func_arg = opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" },
+ { "autoexit", OPT_BOOL | OPT_EXPERT, { &autoexit }, "exit at the end", "" },
+ { "exitonkeydown", OPT_BOOL | OPT_EXPERT, { &exit_on_keydown }, "exit on key down", "" },
+ { "exitonmousedown", OPT_BOOL | OPT_EXPERT, { &exit_on_mousedown }, "exit on mouse down", "" },
+ { "loop", OPT_INT | HAS_ARG | OPT_EXPERT, { &loop }, "set number of times the playback shall be looped", "loop count" },
+ { "framedrop", OPT_BOOL | OPT_EXPERT, { &framedrop }, "drop frames when cpu is too slow", "" },
+ { "infbuf", OPT_BOOL | OPT_EXPERT, { &infinite_buffer }, "don't limit the input buffer size (useful with realtime streams)", "" },
+ { "window_title", OPT_STRING | HAS_ARG, { &window_title }, "set window title", "window title" },
#if CONFIG_AVFILTER
- { "vf", OPT_STRING | HAS_ARG, { (void*)&vfilters }, "video filters", "filter list" },
+ { "vf", OPT_STRING | HAS_ARG, { &vfilters }, "video filters", "filter list" },
#endif
- { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { (void*)&rdftspeed }, "rdft speed", "msecs" },
- { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { (void*)opt_default }, "generic catch all option", "" },
+ { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
+ { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { opt_default }, "generic catch all option", "" },
{ "i", 0, { NULL }, "avconv compatibility dummy option", ""},
{ NULL, },
};
printf("\n");
}
-static void show_help(void)
+void show_help_default(const char *opt, const char *arg)
{
av_log_set_callback(log_callback_help);
show_usage();
- show_help_options(options, "Main options:\n",
- OPT_EXPERT, 0);
- show_help_options(options, "\nAdvanced options:\n",
- OPT_EXPERT, OPT_EXPERT);
+ show_help_options(options, "Main options:", 0, OPT_EXPERT, 0);
+ show_help_options(options, "Advanced options:", OPT_EXPERT, 0, 0);
printf("\n");
show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM);
show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
}
if (!display_disable) {
-#if HAVE_SDL_VIDEO_SIZE
const SDL_VideoInfo *vi = SDL_GetVideoInfo();
fs_screen_width = vi->current_w;
fs_screen_height = vi->current_h;
-#endif
}
SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
av_init_packet(&flush_pkt);
- flush_pkt.data = "FLUSH";
+ flush_pkt.data = (uint8_t *)&flush_pkt;
cur_stream = stream_open(input_filename, file_iformat);