}
#endif
+#undef exit
+
//#define DEBUG_SYNC
#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
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_audio_stream= 0;
static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
static int error_resilience = FF_ER_CAREFUL;
static int error_concealment = 3;
+static int decoder_reorder_pts= 0;
/* current context */
static int is_full_screen;
is->no_background = 0;
}
rect.x = is->xleft + x;
- rect.y = is->xleft + y;
+ rect.y = is->ytop + y;
rect.w = width;
rect.h = height;
SDL_DisplayYUVOverlay(vp->bmp, &rect);
delay -= s->width / 2;
if (delay < s->width)
delay = s->width;
- i_start = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
+
+ i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
+
+ h= INT_MIN;
+ for(i=0; i<1000; i+=channels){
+ int idx= (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
+ int a= s->sample_array[idx];
+ int b= s->sample_array[(idx + 4*channels)%SAMPLE_ARRAY_SIZE];
+ int c= s->sample_array[(idx + 5*channels)%SAMPLE_ARRAY_SIZE];
+ int d= s->sample_array[(idx + 9*channels)%SAMPLE_ARRAY_SIZE];
+ int score= a-d;
+ if(h<score && (b^c)<0){
+ h= score;
+ i_start= idx;
+ }
+ }
+
s->last_i_start = i_start;
} else {
i_start = s->last_i_start;
static void stream_pause(VideoState *is)
{
is->paused = !is->paused;
- if (is->paused) {
+ if (!is->paused) {
is->video_current_pts = get_video_clock(is);
+ is->frame_timer += (av_gettime() - is->video_current_pts_time) / 1000000.0;
}
}
case PIX_FMT_YUV420P:
case PIX_FMT_YUV422P:
case PIX_FMT_YUV444P:
- case PIX_FMT_YUV422:
+ case PIX_FMT_YUYV422:
case PIX_FMT_YUV410P:
case PIX_FMT_YUV411P:
is_yuv = 1;
return queue_picture(is, src_frame, pts);
}
+static uint64_t global_video_pkt_pts= AV_NOPTS_VALUE;
+
+static int my_get_buffer(struct AVCodecContext *c, AVFrame *pic){
+ int ret= avcodec_default_get_buffer(c, pic);
+ uint64_t *pts= av_malloc(sizeof(uint64_t));
+ *pts= global_video_pkt_pts;
+ pic->opaque= pts;
+ return ret;
+}
+
+static void my_release_buffer(struct AVCodecContext *c, AVFrame *pic){
+ if(pic) av_freep(&pic->opaque);
+ avcodec_default_release_buffer(c, pic);
+}
+
static int video_thread(void *arg)
{
VideoState *is = arg;
/* NOTE: ipts is the PTS of the _first_ picture beginning in
this packet, if any */
- pts = 0;
- if (pkt->dts != AV_NOPTS_VALUE)
- pts = av_q2d(is->video_st->time_base)*pkt->dts;
+ global_video_pkt_pts= pkt->pts;
+ len1 = avcodec_decode_video(is->video_st->codec,
+ frame, &got_picture,
+ pkt->data, pkt->size);
+
+ if( (decoder_reorder_pts || pkt->dts == AV_NOPTS_VALUE)
+ && frame->opaque && *(uint64_t*)frame->opaque != AV_NOPTS_VALUE)
+ pts= *(uint64_t*)frame->opaque;
+ else if(pkt->dts != AV_NOPTS_VALUE)
+ pts= pkt->dts;
+ else
+ pts= 0;
+ pts *= av_q2d(is->video_st->time_base);
- len1 = avcodec_decode_video(is->video_st->codec,
- frame, &got_picture,
- pkt->data, pkt->size);
// if (len1 < 0)
// break;
- if (got_picture) {
- if (output_picture2(is, frame, pts) < 0)
- goto the_end;
- }
+ if (got_picture) {
+ if (output_picture2(is, frame, pts) < 0)
+ goto the_end;
+ }
av_free_packet(pkt);
if (step)
if (cur_stream)
}
/* decode one audio frame and returns its uncompressed size */
-static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr)
+static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, int buf_size, double *pts_ptr)
{
AVPacket *pkt = &is->audio_pkt;
int n, len1, data_size;
for(;;) {
/* NOTE: the audio packet can contain several frames */
while (is->audio_pkt_size > 0) {
- len1 = avcodec_decode_audio(is->audio_st->codec,
+ data_size = buf_size;
+ len1 = avcodec_decode_audio2(is->audio_st->codec,
(int16_t *)audio_buf, &data_size,
is->audio_pkt_data, is->audio_pkt_size);
if (len1 < 0) {
cannot have a precise information */
static int audio_write_get_buf_size(VideoState *is)
{
- return is->audio_hw_buf_size - is->audio_buf_index;
+ return is->audio_buf_size - is->audio_buf_index;
}
while (len > 0) {
if (is->audio_buf_index >= is->audio_buf_size) {
- audio_size = audio_decode_frame(is, is->audio_buf, &pts);
+ audio_size = audio_decode_frame(is, is->audio_buf, sizeof(is->audio_buf), &pts);
if (audio_size < 0) {
/* if error, just output silence */
is->audio_buf_size = 1024;
if (!codec ||
avcodec_open(enc, codec) < 0)
return -1;
-#if defined(HAVE_THREADS)
if(thread_count>1)
avcodec_thread_init(enc, thread_count);
-#endif
enc->thread_count= thread_count;
switch(enc->codec_type) {
case CODEC_TYPE_AUDIO:
packet_queue_init(&is->videoq);
is->video_tid = SDL_CreateThread(video_thread, is);
+
+ enc-> get_buffer= my_get_buffer;
+ enc->release_buffer= my_release_buffer;
break;
case CODEC_TYPE_SUBTITLE:
is->subtitle_stream = stream_index;
ap->initial_pause = 1; /* we force a pause when starting an RTSP
stream */
+ ap->width = frame_width;
+ ap->height= frame_height;
+ ap->time_base= (AVRational){1, 25};
+ ap->pix_fmt = frame_pix_fmt;
+
err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
if (err < 0) {
print_error(is->filename, err);
goto fail;
}
is->ic = ic;
-#ifdef CONFIG_NETWORK
+#ifdef CONFIG_RTSP_DEMUXER
use_play = (ic->iformat == &rtsp_demuxer);
#else
use_play = 0;
for(;;) {
if (is->abort_request)
break;
-#ifdef CONFIG_NETWORK
if (is->paused != is->last_paused) {
is->last_paused = is->paused;
if (is->paused)
else
av_read_play(ic);
}
+#ifdef CONFIG_RTSP_DEMUXER
if (is->paused && ic->iformat == &rtsp_demuxer) {
/* wait 10 ms to avoid trying to get another packet */
/* XXX: horrible */
}
}
-void opt_width(const char *arg)
+static void opt_frame_size(const char *arg)
+{
+ if (parse_image_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);
+ }
+}
+
+static void opt_width(const char *arg)
{
screen_width = atoi(arg);
if(screen_width<=0){
}
}
-void opt_height(const char *arg)
+static void opt_height(const char *arg)
{
screen_height = atoi(arg);
if(screen_height<=0){
}
}
-#ifdef CONFIG_NETWORK
-void opt_rtp_tcp(void)
+static void opt_frame_pix_fmt(const char *arg)
+{
+ frame_pix_fmt = avcodec_get_pix_fmt(arg);
+}
+
+#ifdef CONFIG_RTSP_DEMUXER
+static void opt_rtp_tcp(void)
{
/* only tcp protocol */
rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
}
#endif
-void opt_sync(const char *arg)
+static void opt_sync(const char *arg)
{
if (!strcmp(arg, "audio"))
av_sync_type = AV_SYNC_AUDIO_MASTER;
show_help();
}
-void opt_seek(const char *arg)
+static void opt_seek(const char *arg)
{
start_time = parse_date(arg, 1);
}
static void opt_debug(const char *arg)
{
- av_log_set_level(99);
+ av_log_level = 99;
debug = atoi(arg);
}
{ "h", 0, {(void*)show_help}, "show help" },
{ "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" },
{ "bytes", OPT_BOOL, {(void*)&seek_by_bytes}, "seek by bytes" },
{ "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_BOOL |OPT_EXPERT, {(void*)&decoder_reorder_pts}, "let decoder reorder pts", ""},
{ "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
{ "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
{ "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
{ "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
{ "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_resilience}, "set error detection threshold (0-4)", "threshold" },
{ "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
-#ifdef CONFIG_NETWORK
+#ifdef CONFIG_RTSP_DEMUXER
{ "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
#endif
{ "sync", HAS_ARG | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },