SDL_Overlay *bmp;
int width, height; /* source height & width */
int allocated;
+ int reallocate;
enum PixelFormat pix_fmt;
#if CONFIG_AVFILTER
AVStream *audio_st;
PacketQueue audioq;
int audio_hw_buf_size;
- /* samples output by the codec. we reserve more space for avsync
- compensation */
- DECLARE_ALIGNED(16,uint8_t,audio_buf1)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
- DECLARE_ALIGNED(16,uint8_t,audio_buf2)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
+ uint8_t silence_buf[SDL_AUDIO_BUFFER_SIZE];
uint8_t *audio_buf;
+ uint8_t *audio_buf1;
unsigned int audio_buf_size; /* in bytes */
int audio_buf_index; /* in bytes */
AVPacket audio_pkt_temp;
AVPacket audio_pkt;
enum AVSampleFormat audio_src_fmt;
AVAudioConvert *reformat_ctx;
+ AVFrame *frame;
int show_audio; /* if true, display audio samples */
int16_t sample_array[SAMPLE_ARRAY_SIZE];
static SDL_Surface *screen;
+void exit_program(int ret)
+{
+ exit(ret);
+}
+
static int packet_queue_put(PacketQueue *q, AVPacket *pkt);
/* packet queue handling */
&& is->height== screen->h && screen->h == h)
return 0;
-#ifndef __APPLE__
- screen = SDL_SetVideoMode(w, h, 0, flags);
-#else
- /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
+#if defined(__APPLE__) && !SDL_VERSION_ATLEAST(1, 2, 14)
+ /* setting bits_per_pixel = 0 or 32 causes blank video on OS X and older SDL */
screen = SDL_SetVideoMode(w, h, 24, flags);
+#else
+ screen = SDL_SetVideoMode(w, h, 0, flags);
#endif
if (!screen) {
fprintf(stderr, "SDL: could not set video mode - exiting\n");
#if CONFIG_AVFILTER
avfilter_uninit();
#endif
+ avformat_network_deinit();
if (show_status)
printf("\n");
SDL_Quit();
vp = &is->pictq[is->pictq_windex];
/* alloc or resize hardware picture buffer */
- if (!vp->bmp ||
+ if (!vp->bmp || vp->reallocate ||
#if CONFIG_AVFILTER
vp->width != is->out_video_filter->inputs[0]->w ||
vp->height != is->out_video_filter->inputs[0]->h) {
#endif
SDL_Event event;
- vp->allocated = 0;
+ vp->allocated = 0;
+ vp->reallocate = 0;
/* the allocation must be done in the main thread to avoid
locking problems */
pic->linesize[i] = ref->linesize[i];
}
pic->opaque = ref;
- 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;
AVFilterGraph *graph = avfilter_graph_alloc();
AVFilterContext *filt_out = NULL;
int64_t pos;
+ 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;
while (is->paused && !is->videoq.abort_request)
SDL_Delay(10);
#if CONFIG_AVFILTER
+ if ( last_w != is->video_st->codec->width
+ || last_h != is->video_st->codec->height) {
+ av_dlog(NULL, "Changing size %dx%d -> %dx%d\n", last_w, last_h,
+ is->video_st->codec->width, is->video_st->codec->height);
+ avfilter_graph_free(&graph);
+ graph = avfilter_graph_alloc();
+ if ((ret = configure_video_filters(graph, is, vfilters)) < 0)
+ goto the_end;
+ 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;
AVPacket *pkt_temp = &is->audio_pkt_temp;
AVPacket *pkt = &is->audio_pkt;
AVCodecContext *dec= is->audio_st->codec;
- int n, len1, data_size;
+ int n, len1, data_size, got_frame;
double pts;
+ int new_packet = 0;
+ int flush_complete = 0;
for(;;) {
/* NOTE: the audio packet can contain several frames */
- while (pkt_temp->size > 0) {
- data_size = sizeof(is->audio_buf1);
- len1 = avcodec_decode_audio3(dec,
- (int16_t *)is->audio_buf1, &data_size,
- pkt_temp);
+ while (pkt_temp->size > 0 || (!pkt_temp->data && new_packet)) {
+ if (!is->frame) {
+ if (!(is->frame = avcodec_alloc_frame()))
+ return AVERROR(ENOMEM);
+ } else
+ avcodec_get_frame_defaults(is->frame);
+
+ if (flush_complete)
+ break;
+ new_packet = 0;
+ len1 = avcodec_decode_audio4(dec, is->frame, &got_frame, pkt_temp);
if (len1 < 0) {
/* if error, we skip the frame */
pkt_temp->size = 0;
pkt_temp->data += len1;
pkt_temp->size -= len1;
- if (data_size <= 0)
+
+ if (!got_frame) {
+ /* stop sending empty packets if the decoder is finished */
+ if (!pkt_temp->data && dec->codec->capabilities & CODEC_CAP_DELAY)
+ flush_complete = 1;
continue;
+ }
+ data_size = av_samples_get_buffer_size(NULL, dec->channels,
+ is->frame->nb_samples,
+ dec->sample_fmt, 1);
if (dec->sample_fmt != is->audio_src_fmt) {
if (is->reformat_ctx)
}
if (is->reformat_ctx) {
- const void *ibuf[6]= {is->audio_buf1};
- void *obuf[6]= {is->audio_buf2};
+ const void *ibuf[6]= { is->frame->data[0] };
+ void *obuf[6];
int istride[6]= {av_get_bytes_per_sample(dec->sample_fmt)};
int ostride[6]= {2};
int len= data_size/istride[0];
+ obuf[0] = av_realloc(is->audio_buf1, FFALIGN(len * ostride[0], 32));
+ if (!obuf[0]) {
+ return AVERROR(ENOMEM);
+ }
+ is->audio_buf1 = obuf[0];
if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
printf("av_audio_convert() failed\n");
break;
}
- is->audio_buf= is->audio_buf2;
+ is->audio_buf = is->audio_buf1;
/* FIXME: existing code assume that data_size equals framesize*channels*2
remove this legacy cruft */
data_size= len*2;
}else{
- is->audio_buf= is->audio_buf1;
+ is->audio_buf = is->frame->data[0];
}
/* if no pts, then compute it */
}
/* read next packet */
- if (packet_queue_get(&is->audioq, pkt, 1) < 0)
+ if ((new_packet = packet_queue_get(&is->audioq, pkt, 1)) < 0)
return -1;
- if(pkt->data == flush_pkt.data){
+
+ if (pkt->data == flush_pkt.data)
avcodec_flush_buffers(dec);
- continue;
- }
- pkt_temp->data = pkt->data;
- pkt_temp->size = pkt->size;
+ *pkt_temp = *pkt;
/* if update the audio clock with the pts */
if (pkt->pts != AV_NOPTS_VALUE) {
audio_size = audio_decode_frame(is, &pts);
if (audio_size < 0) {
/* if error, just output silence */
- is->audio_buf = is->audio_buf1;
- is->audio_buf_size = 1024;
- memset(is->audio_buf, 0, is->audio_buf_size);
+ is->audio_buf = is->silence_buf;
+ is->audio_buf_size = sizeof(is->silence_buf);
} else {
if (is->show_audio)
update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
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->request_channels = FFMIN(2, avctx->channels);
- } else {
- avctx->request_channels = 2;
- }
- }
+ opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index]);
codec = avcodec_find_decoder(avctx->codec_id);
avctx->debug_mv = debug_mv;
SDL_CloseAudio();
packet_queue_end(&is->audioq);
+ av_free_packet(&is->audio_pkt);
if (is->reformat_ctx)
av_audio_convert_free(is->reformat_ctx);
is->reformat_ctx = NULL;
+ av_freep(&is->audio_buf1);
+ is->audio_buf = NULL;
+ av_freep(&is->frame);
+
+ if (is->rdft) {
+ av_rdft_end(is->rdft);
+ av_freep(&is->rdft_data);
+ is->rdft = NULL;
+ is->rdft_bits = 0;
+ }
break;
case AVMEDIA_TYPE_VIDEO:
packet_queue_abort(&is->videoq);
variable instead of a thread local variable */
static VideoState *global_video_state;
-static int decode_interrupt_cb(void)
+static int decode_interrupt_cb(void *ctx)
{
return (global_video_state && global_video_state->abort_request);
}
is->subtitle_stream = -1;
global_video_state = is;
- avio_set_interrupt_cb(decode_interrupt_cb);
+ ic = avformat_alloc_context();
+ ic->interrupt_callback.callback = decode_interrupt_cb;
err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts);
if (err < 0) {
print_error(is->filename, err);
pkt->stream_index= is->video_stream;
packet_queue_put(&is->videoq, pkt);
}
+ if (is->audio_stream >= 0 &&
+ is->audio_st->codec->codec->capabilities & CODEC_CAP_DELAY) {
+ av_init_packet(pkt);
+ pkt->data = NULL;
+ pkt->size = 0;
+ pkt->stream_index = is->audio_stream;
+ packet_queue_put(&is->audioq, pkt);
+ }
SDL_Delay(10);
if(is->audioq.size + is->videoq.size + is->subtitleq.size ==0){
if(loop!=1 && (!loop || --loop)){
if (is->subtitle_stream >= 0)
stream_component_close(is, is->subtitle_stream);
if (is->ic) {
- av_close_input_file(is->ic);
- is->ic = NULL; /* safety */
+ avformat_close_input(&is->ic);
}
avio_set_interrupt_cb(NULL);
static void toggle_full_screen(void)
{
is_full_screen = !is_full_screen;
+#if defined(__APPLE__) && SDL_VERSION_ATLEAST(1, 2, 14)
+ /* OSX needs to empty the picture_queue */
+ for (int i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
+ cur_stream->pictq[i].reallocate = 1;
+ }
+#endif
video_open(cur_stream);
}
#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", "" },
- { "i", 0, {NULL}, "ffmpeg compatibility dummy option", ""},
+ { "i", 0, {NULL}, "avconv compatibility dummy option", ""},
{ NULL, },
};
show_help_options(options, "\nAdvanced options:\n",
OPT_EXPERT, OPT_EXPERT);
printf("\n");
- av_opt_show2(avcodec_opts[0], NULL,
- AV_OPT_FLAG_DECODING_PARAM, 0);
- printf("\n");
- av_opt_show2(avformat_opts, NULL,
- AV_OPT_FLAG_DECODING_PARAM, 0);
+ show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM);
+ show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
#if !CONFIG_AVFILTER
- printf("\n");
- av_opt_show2(sws_opts, NULL,
- AV_OPT_FLAG_ENCODING_PARAM, 0);
+ show_help_children(sws_get_class(), AV_OPT_FLAG_ENCODING_PARAM);
#endif
printf("\nWhile playing:\n"
"q, ESC quit\n"
);
}
-static void opt_input_file(const char *filename)
+static void opt_input_file(void *optctx, const char *filename)
{
if (input_filename) {
fprintf(stderr, "Argument '%s' provided as input filename, but '%s' was already specified.\n",
int flags;
av_log_set_flags(AV_LOG_SKIP_REPEATED);
+ parse_loglevel(argc, argv, options);
/* register all codecs, demux and protocols */
avcodec_register_all();
avfilter_register_all();
#endif
av_register_all();
+ avformat_network_init();
init_opts();
show_banner();
- parse_options(argc, argv, options, opt_input_file);
+ parse_options(NULL, argc, argv, options, opt_input_file);
if (!input_filename) {
show_usage();