int paused;
int last_paused;
int seek_req;
+ int seek_flags;
int64_t seek_pos;
AVFormatContext *ic;
int dtg_active_format;
/* samples output by the codec. we reserve more space for avsync
compensation */
uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
- int audio_buf_size; /* in bytes */
+ unsigned int audio_buf_size; /* in bytes */
int audio_buf_index; /* in bytes */
AVPacket audio_pkt;
uint8_t *audio_pkt_data;
SDL_mutex *pictq_mutex;
SDL_cond *pictq_cond;
+ SDL_mutex *video_decoder_mutex;
+ SDL_mutex *audio_decoder_mutex;
+
// QETimer *video_timer;
char filename[1024];
int width, height, xleft, ytop;
static int step = 0;
static int thread_count = 1;
static int workaround_bugs = 1;
+static int fast = 0;
+static int lowres = 0;
+static int idct = FF_IDCT_AUTO;
/* current context */
static int is_full_screen;
for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
pkt1 = pkt->next;
av_free_packet(&pkt->pkt);
+ av_freep(&pkt);
}
q->last_pkt = NULL;
q->first_pkt = NULL;
}
/* seek in the stream */
-static void stream_seek(VideoState *is, int64_t pos)
+static void stream_seek(VideoState *is, int64_t pos, int rel)
{
is->seek_pos = pos;
is->seek_req = 1;
+ is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
}
/* pause or resume the video */
pts = pts1;
- /* if B frames are present, and if the current picture is a I
- or P frame, we use the last pts */
- if (is->video_st->codec.has_b_frames &&
- src_frame->pict_type != FF_B_TYPE) {
- /* use last pts */
- pts = is->video_last_P_pts;
- /* get the pts for the next I or P frame if present */
- is->video_last_P_pts = pts1;
- }
-
if (pts != 0) {
/* update video clock with pts, if present */
is->video_clock = pts;
/* NOTE: ipts is the PTS of the _first_ picture beginning in
this packet, if any */
pts = 0;
- if (pkt->pts != AV_NOPTS_VALUE)
- pts = (double)pkt->pts / AV_TIME_BASE;
-
- if (is->video_st->codec.codec_id == CODEC_ID_RAWVIDEO) {
- avpicture_fill((AVPicture *)frame, pkt->data,
- is->video_st->codec.pix_fmt,
- is->video_st->codec.width,
- is->video_st->codec.height);
- frame->pict_type = FF_I_TYPE;
- if (output_picture2(is, frame, pts) < 0)
- goto the_end;
- } else {
+ if (pkt->dts != AV_NOPTS_VALUE)
+ pts = (double)pkt->dts / AV_TIME_BASE;
+
+ SDL_LockMutex(is->video_decoder_mutex);
len1 = avcodec_decode_video(&is->video_st->codec,
frame, &got_picture,
pkt->data, pkt->size);
+ SDL_UnlockMutex(is->video_decoder_mutex);
// if (len1 < 0)
// break;
if (got_picture) {
if (output_picture2(is, frame, pts) < 0)
goto the_end;
}
- }
av_free_packet(pkt);
if (step)
if (cur_stream)
for(;;) {
/* NOTE: the audio packet can contain several frames */
while (is->audio_pkt_size > 0) {
+ SDL_LockMutex(is->audio_decoder_mutex);
len1 = avcodec_decode_audio(&is->audio_st->codec,
(int16_t *)audio_buf, &data_size,
is->audio_pkt_data, is->audio_pkt_size);
+ SDL_UnlockMutex(is->audio_decoder_mutex);
if (len1 < 0) {
/* if error, we skip the frame */
is->audio_pkt_size = 0;
enc->debug_mv = debug_mv;
enc->debug = debug;
enc->workaround_bugs = workaround_bugs;
+ enc->lowres = lowres;
+ if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
+ enc->idct_algo= idct;
+ if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
if (!codec ||
avcodec_open(enc, codec) < 0)
return -1;
-#if defined(HAVE_PTHREADS) || defined(HAVE_W32THREADS)
+#if defined(HAVE_THREADS)
if(thread_count>1)
avcodec_thread_init(enc, thread_count);
#endif
ret = -1;
goto fail;
}
+ ic->pb.eof_reached= 0; //FIXME hack, ffplay maybe shouldnt use url_feof() to test for the end
}
/* if seeking requested, we execute it */
/* add the stream start time */
if (ic->start_time != AV_NOPTS_VALUE)
timestamp += ic->start_time;
- ret = av_seek_frame(ic, -1, timestamp);
+ ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
if (ret < 0) {
fprintf(stderr, "%s: could not seek to position %0.3f\n",
is->filename, (double)timestamp / AV_TIME_BASE);
#endif
if (is->seek_req) {
/* XXX: must lock decoder threads */
- ret = av_seek_frame(is->ic, -1, is->seek_pos);
+ ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
if (ret < 0) {
fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
}else{
}
if (is->video_stream >= 0) {
packet_queue_flush(&is->videoq);
+ SDL_LockMutex(is->video_decoder_mutex);
avcodec_flush_buffers(&ic->streams[video_index]->codec);
+ SDL_UnlockMutex(is->video_decoder_mutex);
}
}
is->seek_req = 0;
}
ret = av_read_frame(ic, pkt);
if (ret < 0) {
- break;
+ if (url_feof(&ic->pb) && url_ferror(&ic->pb) == 0) {
+ SDL_Delay(100); /* wait for user event */
+ continue;
+ } else
+ break;
}
if (pkt->stream_index == is->audio_stream) {
packet_queue_put(&is->audioq, pkt);
/* start video display */
is->pictq_mutex = SDL_CreateMutex();
is->pictq_cond = SDL_CreateCond();
+
+ is->audio_decoder_mutex = SDL_CreateMutex();
+ is->video_decoder_mutex = SDL_CreateMutex();
/* add the refresh timer to draw the picture */
schedule_refresh(is, 40);
}
SDL_DestroyMutex(is->pictq_mutex);
SDL_DestroyCond(is->pictq_cond);
+ SDL_DestroyMutex(is->audio_decoder_mutex);
+ SDL_DestroyMutex(is->video_decoder_mutex);
}
void stream_cycle_channel(VideoState *is, int codec_type)
if (cur_stream) {
pos = get_master_clock(cur_stream);
pos += incr;
- stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE));
+ stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
}
break;
default:
ss = (ns%60);
fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
hh, mm, ss, thh, tmm, tss);
- stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration));
+ stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
}
break;
case SDL_VIDEORESIZE:
static void opt_thread_count(const char *arg)
{
thread_count= atoi(arg);
-#if !defined(HAVE_PTHREADS) && !defined(HAVE_W32THREADS)
+#if !defined(HAVE_THREADS)
fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
#endif
}
{ "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", "" },
+ { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
+ { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
#ifdef CONFIG_NETWORK
{ "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
#endif