/*
- * FFplay : Simple Media Player based on the FFmpeg libraries
+ * ffplay : Simple Media Player based on the Libav libraries
* Copyright (c) 2003 Fabrice Bellard
*
- * This file is part of FFmpeg.
+ * This file is part of Libav.
*
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#define _XOPEN_SOURCE 600
-
#include "config.h"
#include <inttypes.h>
#include <math.h>
#include <limits.h>
#include "libavutil/avstring.h"
#include "libavutil/colorspace.h"
+#include "libavutil/mathematics.h"
#include "libavutil/pixdesc.h"
-#include "libavcore/imgutils.h"
-#include "libavcore/parseutils.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/dict.h"
+#include "libavutil/parseutils.h"
+#include "libavutil/samplefmt.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
# include "libavfilter/avfilter.h"
# include "libavfilter/avfiltergraph.h"
-# include "libavfilter/graphparser.h"
#endif
#include "cmdutils.h"
#include <unistd.h>
#include <assert.h>
-const char program_name[] = "FFplay";
+const char program_name[] = "ffplay";
const int program_birth_year = 2003;
-//#define DEBUG_SYNC
-
#define MAX_QUEUE_SIZE (15 * 1024 * 1024)
#define MIN_AUDIOQ_SIZE (20 * 16 * 1024)
#define MIN_FRAMES 5
int audio_buf_index; /* in bytes */
AVPacket audio_pkt_temp;
AVPacket audio_pkt;
- enum SampleFormat audio_src_fmt;
+ enum AVSampleFormat audio_src_fmt;
AVAudioConvert *reformat_ctx;
int show_audio; /* if true, display audio samples */
char filename[1024];
int width, height, xleft, ytop;
- int64_t faulty_pts;
- int64_t faulty_dts;
- int64_t last_dts_for_fault_detection;
- int64_t last_pts_for_fault_detection;
+ PtsCorrectionContext pts_ctx;
#if CONFIG_AVFILTER
AVFilterContext *out_video_filter; ///<the last filter in the video chain
} VideoState;
static void show_help(void);
-static int audio_write_get_buf_size(VideoState *is);
/* options specified by the user */
static AVInputFormat *file_iformat;
static int fs_screen_height;
static int screen_width = 0;
static int screen_height = 0;
-static int frame_width = 0;
-static int frame_height = 0;
-static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
static int audio_disable;
static int video_disable;
static int wanted_stream[AVMEDIA_TYPE_NB]={
SDL_FillRect(screen, &rect, color);
}
-#if 0
-/* draw only the border of a rectangle */
-void fill_border(VideoState *s, int x, int y, int w, int h, int color)
-{
- int w1, w2, h1, h2;
-
- /* fill the background */
- w1 = x;
- if (w1 < 0)
- w1 = 0;
- w2 = s->width - (x + w);
- if (w2 < 0)
- w2 = 0;
- h1 = y;
- if (h1 < 0)
- h1 = 0;
- h2 = s->height - (y + h);
- if (h2 < 0)
- h2 = 0;
- fill_rectangle(screen,
- s->xleft, s->ytop,
- w1, s->height,
- color);
- fill_rectangle(screen,
- s->xleft + s->width - w2, s->ytop,
- w2, s->height,
- color);
- fill_rectangle(screen,
- s->xleft + w1, s->ytop,
- s->width - w1 - w2, h1,
- color);
- fill_rectangle(screen,
- s->xleft + w1, s->ytop + s->height - h2,
- s->width - w1 - w2, h2,
- color);
-}
-#endif
-
#define ALPHA_BLEND(a, oldp, newp, s)\
((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
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)
{
}
x = (is->width - width) / 2;
y = (is->height - height) / 2;
- if (!is->no_background) {
- /* fill the background */
- // fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
- } else {
- is->no_background = 0;
- }
+ is->no_background = 0;
rect.x = is->xleft + x;
rect.y = is->ytop + y;
rect.w = width;
rect.h = height;
SDL_DisplayYUVOverlay(vp->bmp, &rect);
- } else {
-#if 0
- fill_rectangle(screen,
- is->xleft, is->ytop, is->width, is->height,
- QERGB(0x00, 0x00, 0x00));
-#endif
}
}
+/* 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;
{
VideoState *is= opaque;
while(!is->abort_request){
- SDL_Event event;
- event.type = FF_REFRESH_EVENT;
- event.user.data1 = opaque;
+ SDL_Event event;
+ event.type = FF_REFRESH_EVENT;
+ event.user.data1 = opaque;
if(!is->refresh){
is->refresh=1;
- SDL_PushEvent(&event);
+ 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
}
}
}
is->frame_timer += delay;
-#if defined(DEBUG_SYNC)
- printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
- delay, actual_delay, frame_current_pts, -diff);
-#endif
+
+ av_dlog(NULL, "video: delay=%0.3f pts=%0.3f A-V=%f\n",
+ delay, frame_current_pts, -diff);
return is->frame_timer;
}
}
/* display picture */
- video_display(is);
+ if (!display_disable)
+ video_display(is);
/* update queue size and signal for next picture */
if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
than nothing, just to test the implementation */
/* display picture */
- video_display(is);
+ if (!display_disable)
+ video_display(is);
}
if (show_status) {
static int64_t last_time;
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->faulty_dts, is->faulty_pts);
+ get_master_clock(is), av_diff, FFMAX(is->skip_frames-1, 0), aqsize / 1024, vqsize / 1024, sqsize, is->pts_ctx.num_faulty_dts, is->pts_ctx.num_faulty_pts);
fflush(stdout);
last_time = cur_time;
}
static void do_exit(void)
{
- int i;
if (cur_stream) {
stream_close(cur_stream);
cur_stream = NULL;
}
- for (i = 0; i < AVMEDIA_TYPE_NB; i++)
- av_free(avcodec_opts[i]);
- av_free(avformat_opts);
- av_free(sws_opts);
+ uninit_opts();
#if CONFIG_AVFILTER
avfilter_uninit();
#endif
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;
+#else
+ int dst_pix_fmt = PIX_FMT_YUV420P;
#endif
/* wait until we have space to put a new picture */
SDL_LockMutex(is->pictq_mutex);
/* 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];
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;
+ int got_picture, i;
- if (packet_queue_get(&is->videoq, pkt, 1) < 0)
- return -1;
+ if (packet_queue_get(&is->videoq, pkt, 1) < 0)
+ return -1;
- if(pkt->data == flush_pkt.data){
- avcodec_flush_buffers(is->video_st->codec);
+ if (pkt->data == flush_pkt.data) {
+ avcodec_flush_buffers(is->video_st->codec);
- SDL_LockMutex(is->pictq_mutex);
- //Make sure there are no long delay timers (ideally we should just flush the que but thats harder)
- for(i=0; i<VIDEO_PICTURE_QUEUE_SIZE; i++){
- is->pictq[i].target_clock= 0;
- }
- while (is->pictq_size && !is->videoq.abort_request) {
- SDL_CondWait(is->pictq_cond, is->pictq_mutex);
- }
- is->video_current_pos= -1;
- SDL_UnlockMutex(is->pictq_mutex);
-
- is->last_dts_for_fault_detection=
- is->last_pts_for_fault_detection= INT64_MIN;
- is->frame_last_pts= AV_NOPTS_VALUE;
- is->frame_last_delay = 0;
- is->frame_timer = (double)av_gettime() / 1000000.0;
- is->skip_frames= 1;
- is->skip_frames_index= 0;
- return 0;
+ SDL_LockMutex(is->pictq_mutex);
+ //Make sure there are no long delay timers (ideally we should just flush the que but thats harder)
+ for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
+ is->pictq[i].target_clock= 0;
}
+ while (is->pictq_size && !is->videoq.abort_request) {
+ SDL_CondWait(is->pictq_cond, is->pictq_mutex);
+ }
+ is->video_current_pos = -1;
+ SDL_UnlockMutex(is->pictq_mutex);
- /* 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_video2(is->video_st->codec,
- frame, &got_picture,
- pkt);
-
- if (got_picture) {
- if(pkt->dts != AV_NOPTS_VALUE){
- is->faulty_dts += pkt->dts <= is->last_dts_for_fault_detection;
- is->last_dts_for_fault_detection= pkt->dts;
- }
- if(frame->reordered_opaque != AV_NOPTS_VALUE){
- is->faulty_pts += frame->reordered_opaque <= is->last_pts_for_fault_detection;
- is->last_pts_for_fault_detection= frame->reordered_opaque;
- }
+ init_pts_correction(&is->pts_ctx);
+ is->frame_last_pts = AV_NOPTS_VALUE;
+ is->frame_last_delay = 0;
+ is->frame_timer = (double)av_gettime() / 1000000.0;
+ is->skip_frames = 1;
+ is->skip_frames_index = 0;
+ return 0;
+ }
+
+ avcodec_decode_video2(is->video_st->codec, frame, &got_picture, pkt);
+
+ if (got_picture) {
+ if (decoder_reorder_pts == -1) {
+ *pts = guess_correct_pts(&is->pts_ctx, frame->pkt_pts, frame->pkt_dts);
+ } else if (decoder_reorder_pts) {
+ *pts = frame->pkt_pts;
+ } else {
+ *pts = frame->pkt_dts;
}
- if( ( decoder_reorder_pts==1
- || (decoder_reorder_pts && is->faulty_pts<is->faulty_dts)
- || pkt->dts == AV_NOPTS_VALUE)
- && frame->reordered_opaque != AV_NOPTS_VALUE)
- *pts= frame->reordered_opaque;
- else if(pkt->dts != AV_NOPTS_VALUE)
- *pts= pkt->dts;
- else
- *pts= 0;
+ if (*pts == AV_NOPTS_VALUE) {
+ *pts = 0;
+ }
-// if (len1 < 0)
-// break;
- if (got_picture){
is->skip_frames_index += 1;
if(is->skip_frames_index >= is->skip_frames){
is->skip_frames_index -= FFMAX(is->skip_frames, 1.0);
int perms = AV_PERM_WRITE;
int i, w, h, stride[4];
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(!(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 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];
pic->age = INT_MAX;
pic->type = FF_BUFFER_TYPE_USER;
pic->reordered_opaque = codec->reordered_opaque;
+ if(codec->pkt) pic->pkt_pts = codec->pkt->pts;
+ else pic->pkt_pts = AV_NOPTS_VALUE;
return 0;
}
}
pic->reordered_opaque = codec->reordered_opaque;
+ if(codec->pkt) pic->pkt_pts = codec->pkt->pts;
+ else pic->pkt_pts = AV_NOPTS_VALUE;
return 0;
}
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();
link->w = c->width;
link->h = c->height;
+ link->time_base = priv->is->video_st->time_base;
return 0;
}
{ .name = NULL }},
};
-static void output_end_frame(AVFilterLink *link)
-{
-}
-
-static int output_query_formats(AVFilterContext *ctx)
-{
- enum PixelFormat pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
-
- avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
- return 0;
-}
-
-static int get_filtered_video_frame(AVFilterContext *ctx, AVFrame *frame,
- int64_t *pts, int64_t *pos)
-{
- AVFilterBufferRef *pic;
-
- if(avfilter_request_frame(ctx->inputs[0]))
- return -1;
- if(!(pic = ctx->inputs[0]->cur_buf))
- return -1;
- ctx->inputs[0]->cur_buf = NULL;
-
- frame->opaque = pic;
- *pts = pic->pts;
- *pos = pic->pos;
-
- memcpy(frame->data, pic->data, sizeof(frame->data));
- memcpy(frame->linesize, pic->linesize, sizeof(frame->linesize));
-
- return 1;
-}
-
-static AVFilter output_filter =
-{
- .name = "ffplay_output",
-
- .query_formats = output_query_formats,
-
- .inputs = (AVFilterPad[]) {{ .name = "default",
- .type = AVMEDIA_TYPE_VIDEO,
- .end_frame = output_end_frame,
- .min_perms = AV_PERM_READ, },
- { .name = NULL }},
- .outputs = (AVFilterPad[]) {{ .name = NULL }},
-};
-#endif /* CONFIG_AVFILTER */
-
-static int video_thread(void *arg)
+static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters)
{
- VideoState *is = arg;
- AVFrame *frame= avcodec_alloc_frame();
- int64_t pts_int;
- double pts;
- int ret;
-
-#if CONFIG_AVFILTER
- int64_t pos;
char sws_flags_str[128];
+ int ret;
+ FFSinkContext ffsink_ctx = { .pix_fmt = PIX_FMT_YUV420P };
AVFilterContext *filt_src = NULL, *filt_out = NULL;
- AVFilterGraph *graph = av_mallocz(sizeof(AVFilterGraph));
snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%d", sws_flags);
graph->scale_sws_opts = av_strdup(sws_flags_str);
- if (avfilter_open(&filt_src, &input_filter, "src") < 0) goto the_end;
- if (avfilter_open(&filt_out, &output_filter, "out") < 0) goto the_end;
-
- if(avfilter_init_filter(filt_src, NULL, is)) goto the_end;
- if(avfilter_init_filter(filt_out, NULL, frame)) goto the_end;
-
+ if ((ret = avfilter_graph_create_filter(&filt_src, &input_filter, "src",
+ NULL, is, graph)) < 0)
+ return ret;
+ if ((ret = avfilter_graph_create_filter(&filt_out, &ffsink, "out",
+ NULL, &ffsink_ctx, graph)) < 0)
+ return ret;
if(vfilters) {
AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut));
AVFilterInOut *inputs = av_malloc(sizeof(AVFilterInOut));
outputs->name = av_strdup("in");
- outputs->filter = filt_src;
+ outputs->filter_ctx = filt_src;
outputs->pad_idx = 0;
outputs->next = NULL;
inputs->name = av_strdup("out");
- inputs->filter = filt_out;
+ inputs->filter_ctx = filt_out;
inputs->pad_idx = 0;
inputs->next = NULL;
- if (avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL) < 0)
- goto the_end;
+ if ((ret = avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL)) < 0)
+ return ret;
av_freep(&vfilters);
} else {
- if(avfilter_link(filt_src, 0, filt_out, 0) < 0) goto the_end;
+ if ((ret = avfilter_link(filt_src, 0, filt_out, 0)) < 0)
+ return ret;
}
- avfilter_graph_add_filter(graph, filt_src);
- avfilter_graph_add_filter(graph, filt_out);
- if(avfilter_graph_check_validity(graph, NULL)) goto the_end;
- if(avfilter_graph_config_formats(graph, NULL)) goto the_end;
- if(avfilter_graph_config_links(graph, NULL)) goto the_end;
+ if ((ret = avfilter_graph_config(graph, NULL)) < 0)
+ return ret;
is->out_video_filter = filt_out;
+
+ return ret;
+}
+
+#endif /* CONFIG_AVFILTER */
+
+static int video_thread(void *arg)
+{
+ VideoState *is = arg;
+ AVFrame *frame= avcodec_alloc_frame();
+ int64_t pts_int;
+ 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;
+ filt_out = is->out_video_filter;
#endif
for(;;) {
#if !CONFIG_AVFILTER
AVPacket pkt;
+#else
+ AVFilterBufferRef *picref;
+ AVRational tb;
#endif
while (is->paused && !is->videoq.abort_request)
SDL_Delay(10);
#if CONFIG_AVFILTER
- ret = get_filtered_video_frame(filt_out, frame, &pts_int, &pos);
+ ret = get_filtered_video_frame(filt_out, frame, &picref, &tb);
+ if (picref) {
+ pts_int = picref->pts;
+ pos = picref->pos;
+ frame->opaque = picref;
+ }
+
+ 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);
+ }
#else
ret = get_video_frame(is, frame, &pts_int, &pkt);
#endif
}
the_end:
#if CONFIG_AVFILTER
- avfilter_graph_destroy(graph);
- av_freep(&graph);
+ avfilter_graph_free(&graph);
#endif
av_free(frame);
return 0;
VideoState *is = arg;
SubPicture *sp;
AVPacket pkt1, *pkt = &pkt1;
- int len1, got_subtitle;
+ int got_subtitle;
double pts;
int i, j;
int r, g, b, y, u, v, a;
SDL_UnlockMutex(is->subpq_mutex);
if (is->subtitleq.abort_request)
- goto the_end;
+ return 0;
sp = &is->subpq[is->subpq_windex];
if (pkt->pts != AV_NOPTS_VALUE)
pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
- len1 = avcodec_decode_subtitle2(is->subtitle_st->codec,
- &sp->sub, &got_subtitle,
- pkt);
-// if (len1 < 0)
-// break;
+ avcodec_decode_subtitle2(is->subtitle_st->codec, &sp->sub,
+ &got_subtitle, pkt);
+
if (got_subtitle && sp->sub.format == 0) {
sp->pts = pts;
SDL_UnlockMutex(is->subpq_mutex);
}
av_free_packet(pkt);
-// if (step)
-// if (cur_stream)
-// stream_pause(cur_stream);
}
- the_end:
return 0;
}
/* copy samples for viewing in editor window */
static void update_sample_display(VideoState *is, short *samples, int samples_size)
{
- int size, len, channels;
-
- channels = is->audio_st->codec->channels;
+ int size, len;
size = samples_size / sizeof(short);
while (size > 0) {
samples_size = wanted_size;
}
}
-#if 0
- printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
- diff, avg_diff, samples_size - samples_size1,
- is->audio_clock, is->video_clock, is->audio_diff_threshold);
-#endif
+ av_dlog(NULL, "diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
+ diff, avg_diff, samples_size - samples_size1,
+ is->audio_clock, is->video_clock, is->audio_diff_threshold);
}
} else {
/* too big difference : may be initial PTS errors, so
if (dec->sample_fmt != is->audio_src_fmt) {
if (is->reformat_ctx)
av_audio_convert_free(is->reformat_ctx);
- is->reformat_ctx= av_audio_convert_alloc(SAMPLE_FMT_S16, 1,
+ is->reformat_ctx= av_audio_convert_alloc(AV_SAMPLE_FMT_S16, 1,
dec->sample_fmt, 1, NULL, 0);
if (!is->reformat_ctx) {
fprintf(stderr, "Cannot convert %s sample format to %s sample format\n",
- avcodec_get_sample_fmt_name(dec->sample_fmt),
- avcodec_get_sample_fmt_name(SAMPLE_FMT_S16));
+ av_get_sample_fmt_name(dec->sample_fmt),
+ av_get_sample_fmt_name(AV_SAMPLE_FMT_S16));
break;
}
is->audio_src_fmt= dec->sample_fmt;
if (is->reformat_ctx) {
const void *ibuf[6]= {is->audio_buf1};
void *obuf[6]= {is->audio_buf2};
- int istride[6]= {av_get_bits_per_sample_format(dec->sample_fmt)/8};
+ int istride[6]= {av_get_bytes_per_sample(dec->sample_fmt)};
int ostride[6]= {2};
int len= data_size/istride[0];
if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
n = 2 * dec->channels;
is->audio_clock += (double)data_size /
(double)(n * dec->sample_rate);
-#if defined(DEBUG_SYNC)
+#ifdef DEBUG
{
static double last_clock;
printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
}
}
-/* 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)
{
AVCodecContext *avctx;
AVCodec *codec;
SDL_AudioSpec wanted_spec, spec;
+ AVDictionary *opts;
+ AVDictionaryEntry *t = NULL;
if (stream_index < 0 || stream_index >= ic->nb_streams)
return -1;
avctx = ic->streams[stream_index]->codec;
+ opts = filter_codec_opts(codec_opts, avctx->codec_id, 0);
+
/* prepare audio output */
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
if (avctx->channels > 0) {
avctx->skip_loop_filter= skip_loop_filter;
avctx->error_recognition= error_recognition;
avctx->error_concealment= error_concealment;
- avcodec_thread_init(avctx, thread_count);
-
- set_context_opts(avctx, avcodec_opts[avctx->codec_type], 0);
+ avctx->thread_count= thread_count;
if (!codec ||
- avcodec_open(avctx, codec) < 0)
+ avcodec_open2(avctx, codec, &opts) < 0)
return -1;
+ if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
+ av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
+ return AVERROR_OPTION_NOT_FOUND;
+ }
/* prepare audio output */
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
return -1;
}
is->audio_hw_buf_size = spec.size;
- is->audio_src_fmt= SAMPLE_FMT_S16;
+ is->audio_src_fmt= AV_SAMPLE_FMT_S16;
}
ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
is->video_stream = stream_index;
is->video_st = ic->streams[stream_index];
-// is->video_current_pts_time = av_gettime();
-
packet_queue_init(&is->videoq);
is->video_tid = SDL_CreateThread(video_thread, is);
break;
static int decode_thread(void *arg)
{
VideoState *is = arg;
- AVFormatContext *ic;
+ AVFormatContext *ic = NULL;
int err, i, ret;
int st_index[AVMEDIA_TYPE_NB];
- int st_count[AVMEDIA_TYPE_NB]={0};
- int st_best_packet_count[AVMEDIA_TYPE_NB];
AVPacket pkt1, *pkt = &pkt1;
- AVFormatParameters params, *ap = ¶ms;
int eof=0;
int pkt_in_play_range = 0;
-
- ic = avformat_alloc_context();
+ AVDictionaryEntry *t;
+ AVDictionary **opts;
+ int orig_nb_streams;
memset(st_index, -1, sizeof(st_index));
- memset(st_best_packet_count, -1, sizeof(st_best_packet_count));
is->video_stream = -1;
is->audio_stream = -1;
is->subtitle_stream = -1;
global_video_state = is;
- url_set_interrupt_cb(decode_interrupt_cb);
-
- memset(ap, 0, sizeof(*ap));
-
- ap->prealloced_context = 1;
- ap->width = frame_width;
- ap->height= frame_height;
- ap->time_base= (AVRational){1, 25};
- ap->pix_fmt = frame_pix_fmt;
+ avio_set_interrupt_cb(decode_interrupt_cb);
- set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM);
-
- err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
+ err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts);
if (err < 0) {
print_error(is->filename, err);
ret = -1;
goto fail;
}
+ if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
+ av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
+ ret = AVERROR_OPTION_NOT_FOUND;
+ goto fail;
+ }
is->ic = ic;
if(genpts)
ic->flags |= AVFMT_FLAG_GENPTS;
- err = av_find_stream_info(ic);
+ opts = setup_find_stream_info_opts(ic);
+ orig_nb_streams = ic->nb_streams;
+
+ err = avformat_find_stream_info(ic, opts);
if (err < 0) {
fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
ret = -1;
goto fail;
}
+ for (i = 0; i < orig_nb_streams; i++)
+ av_dict_free(&opts[i]);
+ av_freep(&opts);
+
if(ic->pb)
ic->pb->eof_reached= 0; //FIXME hack, ffplay maybe should not use url_feof() to test for the end
}
}
- for(i = 0; i < ic->nb_streams; i++) {
- AVStream *st= ic->streams[i];
- AVCodecContext *avctx = st->codec;
+ for (i = 0; i < ic->nb_streams; i++)
ic->streams[i]->discard = AVDISCARD_ALL;
- if(avctx->codec_type >= (unsigned)AVMEDIA_TYPE_NB)
- continue;
- if(st_count[avctx->codec_type]++ != wanted_stream[avctx->codec_type] && wanted_stream[avctx->codec_type] >= 0)
- continue;
-
- if(st_best_packet_count[avctx->codec_type] >= st->codec_info_nb_frames)
- continue;
- st_best_packet_count[avctx->codec_type]= st->codec_info_nb_frames;
-
- switch(avctx->codec_type) {
- case AVMEDIA_TYPE_AUDIO:
- if (!audio_disable)
- st_index[AVMEDIA_TYPE_AUDIO] = i;
- break;
- case AVMEDIA_TYPE_VIDEO:
- case AVMEDIA_TYPE_SUBTITLE:
- if (!video_disable)
- st_index[avctx->codec_type] = i;
- break;
- default:
- break;
- }
- }
+ if (!video_disable)
+ st_index[AVMEDIA_TYPE_VIDEO] =
+ av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,
+ wanted_stream[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
+ if (!audio_disable)
+ st_index[AVMEDIA_TYPE_AUDIO] =
+ av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,
+ wanted_stream[AVMEDIA_TYPE_AUDIO],
+ st_index[AVMEDIA_TYPE_VIDEO],
+ NULL, 0);
+ if (!video_disable)
+ st_index[AVMEDIA_TYPE_SUBTITLE] =
+ av_find_best_stream(ic, AVMEDIA_TYPE_SUBTITLE,
+ wanted_stream[AVMEDIA_TYPE_SUBTITLE],
+ (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
+ st_index[AVMEDIA_TYPE_AUDIO] :
+ 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);
}
/* open the streams */
SDL_Delay(10);
continue;
}
- if(url_feof(ic->pb) || eof) {
+ if(eof) {
if(is->video_stream >= 0){
av_init_packet(pkt);
pkt->data=NULL;
}
ret = av_read_frame(ic, pkt);
if (ret < 0) {
- if (ret == AVERROR_EOF)
+ if (ret == AVERROR_EOF || (ic->pb && ic->pb->eof_reached))
eof=1;
- if (url_ferror(ic->pb))
+ if (ic->pb && ic->pb->error)
break;
SDL_Delay(100); /* wait for user event */
continue;
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;
static void toggle_full_screen(void)
{
is_full_screen = !is_full_screen;
- if (!fs_screen_width) {
- /* use default SDL method */
-// SDL_WM_ToggleFullScreen(screen);
- }
video_open(cur_stream);
}
}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
}
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;
}
}
-static void opt_frame_size(const char *arg)
+static int opt_frame_size(const char *opt, const char *arg)
{
- if (av_parse_video_size(&frame_width, &frame_height, arg) < 0) {
- fprintf(stderr, "Incorrect frame size\n");
- exit(1);
- }
- if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
- fprintf(stderr, "Frame size must be a multiple of 2\n");
- exit(1);
- }
+ 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)
return 0;
}
-static void opt_format(const char *arg)
+static int opt_format(const char *opt, const char *arg)
{
file_iformat = av_find_input_format(arg);
if (!file_iformat) {
fprintf(stderr, "Unknown input format: %s\n", arg);
- exit(1);
+ return AVERROR(EINVAL);
}
+ return 0;
}
-static void opt_frame_pix_fmt(const char *arg)
+static int opt_frame_pix_fmt(const char *opt, const char *arg)
{
- frame_pix_fmt = av_get_pix_fmt(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 const OptionDef options[] = {
#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" },
+ { "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" },
{ "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 | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
- { "t", HAS_ARG | OPT_FUNC2, {(void*)&opt_duration}, "play \"duration\" seconds of audio/video", "duration" },
+ { "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_FUNC2 | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
+ { "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_FUNC2 | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
+ { "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", ""},
{ "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
{ "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_recognition}, "set error detection threshold (0-4)", "threshold" },
{ "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
- { "sync", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
- { "threads", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
+ { "sync", HAS_ARG | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
+ { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
{ "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", "" },
{ "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" },
- { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
+ { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
+ { "i", 0, {NULL}, "ffmpeg compatibility dummy option", ""},
{ NULL, },
};
/* Called from the main */
int main(int argc, char **argv)
{
- int flags, i;
+ int flags;
av_log_set_flags(AV_LOG_SKIP_REPEATED);
#endif
av_register_all();
- for(i=0; i<AVMEDIA_TYPE_NB; i++){
- avcodec_opts[i]= avcodec_alloc_context2(i);
- }
- avformat_opts = avformat_alloc_context();
-#if !CONFIG_AVFILTER
- sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
-#endif
+ init_opts();
show_banner();