#include <inttypes.h>
#include <math.h>
#include <limits.h>
+#include <signal.h>
#include "libavutil/avstring.h"
#include "libavutil/colorspace.h"
#include "libavutil/mathematics.h"
static enum AVDiscard skip_frame = AVDISCARD_DEFAULT;
static enum AVDiscard skip_idct = AVDISCARD_DEFAULT;
static enum AVDiscard skip_loop_filter = AVDISCARD_DEFAULT;
-static int error_recognition = FF_ER_CAREFUL;
static int error_concealment = 3;
static int decoder_reorder_pts = -1;
static int autoexit;
exit(0);
}
+static void sigterm_handler(int sig)
+{
+ exit(123);
+}
+
static int video_open(VideoState *is, int force_set_video_mode)
{
int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
}
}
-/* return the new audio buffer size (samples can be added or deleted
- to get better sync if video or external master clock) */
-static int synchronize_audio(VideoState *is, short *samples,
- int samples_size1, double pts)
+/* return the wanted number of samples to get better sync if sync_type is video
+ * or external master clock */
+static int synchronize_audio(VideoState *is, int nb_samples)
{
- int n, samples_size;
- double ref_clock;
-
- n = av_get_bytes_per_sample(is->audio_tgt_fmt) * is->audio_tgt_channels;
- samples_size = samples_size1;
+ int wanted_nb_samples = nb_samples;
/* if not master, then we try to remove or add samples to correct the clock */
if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
double diff, avg_diff;
- int wanted_size, min_size, max_size, nb_samples;
+ int min_nb_samples, max_nb_samples;
- ref_clock = get_master_clock(is);
- diff = get_audio_clock(is) - ref_clock;
+ diff = get_audio_clock(is) - get_master_clock(is);
if (diff < AV_NOSYNC_THRESHOLD) {
is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
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_tgt_freq) * n);
- nb_samples = samples_size / n;
-
- min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
- max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
- if (wanted_size < min_size)
- wanted_size = min_size;
- else if (wanted_size > FFMIN3(max_size, samples_size, sizeof(is->audio_buf2)))
- wanted_size = FFMIN3(max_size, samples_size, sizeof(is->audio_buf2));
-
- /* add or remove samples to correction the synchro */
- if (wanted_size < samples_size) {
- /* remove samples */
- samples_size = wanted_size;
- } else if (wanted_size > samples_size) {
- uint8_t *samples_end, *q;
- int nb;
-
- /* add samples */
- nb = (samples_size - wanted_size);
- samples_end = (uint8_t *)samples + samples_size - n;
- q = samples_end + n;
- while (nb > 0) {
- memcpy(q, samples_end, n);
- q += n;
- nb -= n;
- }
- samples_size = wanted_size;
- }
+ wanted_nb_samples = nb_samples + (int)(diff * is->audio_src_freq);
+ min_nb_samples = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX) / 100));
+ max_nb_samples = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX) / 100));
+ wanted_nb_samples = FFMIN(FFMAX(wanted_nb_samples, min_nb_samples), max_nb_samples);
}
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,
+ diff, avg_diff, wanted_nb_samples - nb_samples,
is->audio_clock, is->video_clock, is->audio_diff_threshold);
}
} else {
}
}
- return samples_size;
+ return wanted_nb_samples;
}
/* decode one audio frame and returns its uncompressed size */
double pts;
int new_packet = 0;
int flush_complete = 0;
+ int wanted_nb_samples;
for (;;) {
/* NOTE: the audio packet can contain several frames */
dec->sample_fmt, 1);
dec_channel_layout = (dec->channel_layout && dec->channels == av_get_channel_layout_nb_channels(dec->channel_layout)) ? dec->channel_layout : av_get_default_channel_layout(dec->channels);
+ wanted_nb_samples = synchronize_audio(is, is->frame->nb_samples);
- if (dec->sample_fmt != is->audio_src_fmt || dec_channel_layout != is->audio_src_channel_layout || dec->sample_rate != is->audio_src_freq) {
+ if (dec->sample_fmt != is->audio_src_fmt ||
+ dec_channel_layout != is->audio_src_channel_layout ||
+ dec->sample_rate != is->audio_src_freq ||
+ (wanted_nb_samples != is->frame->nb_samples && !is->swr_ctx)) {
if (is->swr_ctx)
swr_free(&is->swr_ctx);
is->swr_ctx = swr_alloc_set_opts(NULL,
if (is->swr_ctx) {
const uint8_t *in[] = { is->frame->data[0] };
uint8_t *out[] = {is->audio_buf2};
+ if (wanted_nb_samples != is->frame->nb_samples) {
+ if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - is->frame->nb_samples) * is->audio_tgt_freq / dec->sample_rate,
+ wanted_nb_samples * is->audio_tgt_freq / dec->sample_rate) < 0) {
+ fprintf(stderr, "swr_set_compensation() failed\n");
+ break;
+ }
+ }
len2 = swr_convert(is->swr_ctx, out, sizeof(is->audio_buf2) / is->audio_tgt_channels / av_get_bytes_per_sample(is->audio_tgt_fmt),
- in, data_size / dec->channels / av_get_bytes_per_sample(dec->sample_fmt));
+ in, is->frame->nb_samples);
if (len2 < 0) {
fprintf(stderr, "audio_resample() failed\n");
break;
VideoState *is = opaque;
int audio_size, len1;
int bytes_per_sec;
+ int frame_size = av_samples_get_buffer_size(NULL, is->audio_tgt_channels, 1, is->audio_tgt_fmt, 1);
double pts;
audio_callback_time = av_gettime();
if (audio_size < 0) {
/* if error, just output silence */
is->audio_buf = is->silence_buf;
- is->audio_buf_size = sizeof(is->silence_buf);
+ is->audio_buf_size = sizeof(is->silence_buf) / frame_size * frame_size;
} else {
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);
is->audio_buf_size = audio_size;
}
is->audio_buf_index = 0;
AVDictionary *opts;
AVDictionaryEntry *t = NULL;
int64_t wanted_channel_layout = 0;
+ int wanted_nb_channels;
+ const char *env;
if (stream_index < 0 || stream_index >= ic->nb_streams)
return -1;
avctx->skip_frame = skip_frame;
avctx->skip_idct = skip_idct;
avctx->skip_loop_filter = skip_loop_filter;
- avctx->error_recognition = error_recognition;
avctx->error_concealment = error_concealment;
if(avctx->lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
avctx->flags |= CODEC_FLAG_EMU_EDGE;
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
- wanted_channel_layout = (avctx->channel_layout && avctx->channels == av_get_channel_layout_nb_channels(avctx->channels)) ? avctx->channel_layout : av_get_default_channel_layout(avctx->channels);
- wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX;
+ env = SDL_getenv("SDL_AUDIO_CHANNELS");
+ if (env)
+ wanted_channel_layout = av_get_default_channel_layout(SDL_atoi(env));
+ if (!wanted_channel_layout) {
+ wanted_channel_layout = (avctx->channel_layout && avctx->channels == av_get_channel_layout_nb_channels(avctx->channel_layout)) ? avctx->channel_layout : av_get_default_channel_layout(avctx->channels);
+ wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX;
+ wanted_nb_channels = av_get_channel_layout_nb_channels(wanted_channel_layout);
+ /* SDL only supports 1, 2, 4 or 6 channels at the moment, so we have to make sure not to request anything else. */
+ while (wanted_nb_channels > 0 && (wanted_nb_channels == 3 || wanted_nb_channels == 5 || wanted_nb_channels > 6)) {
+ wanted_nb_channels--;
+ wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels);
+ }
+ }
wanted_spec.channels = av_get_channel_layout_nb_channels(wanted_channel_layout);
wanted_spec.freq = avctx->sample_rate;
if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
}
}
+ if (!av_dict_get(opts, "threads", NULL, 0))
+ av_dict_set(&opts, "threads", "auto", 0);
if (!codec ||
avcodec_open2(avctx, codec, &opts) < 0)
return -1;
static void toggle_full_screen(VideoState *is)
{
- int i;
+ av_unused int i;
is_full_screen = !is_full_screen;
#if defined(__APPLE__) && SDL_VERSION_ATLEAST(1, 2, 14)
/* OS X needs to reallocate the SDL overlays */
{ "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" },
- { "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_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", "" },
static void show_usage(void)
{
- printf("Simple media player\n");
- printf("usage: %s [options] input_file\n", program_name);
- printf("\n");
+ av_log(NULL, AV_LOG_INFO, "Simple media player\n");
+ av_log(NULL, AV_LOG_INFO, "usage: %s [options] input_file\n", program_name);
+ av_log(NULL, AV_LOG_INFO, "\n");
}
static int opt_help(const char *opt, const char *arg)
init_opts();
+ signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */
+ signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */
+
show_banner(argc, argv, options);
parse_options(NULL, argc, argv, options, opt_input_file);