X-Git-Url: https://rtime.felk.cvut.cz/gitweb/frescor/ffmpeg.git/blobdiff_plain/59a227516e5c2edd9ce063ccbd2d3020c98f991c..HEAD:/ffplay.c diff --git a/ffplay.c b/ffplay.c index c3af25932..cc12b4a97 100644 --- a/ffplay.c +++ b/ffplay.c @@ -110,6 +110,7 @@ typedef struct VideoState { int seek_req; int seek_flags; int64_t seek_pos; + int64_t seek_rel; AVFormatContext *ic; int dtg_active_format; @@ -134,9 +135,8 @@ typedef struct VideoState { uint8_t *audio_buf; unsigned int audio_buf_size; /* in bytes */ int audio_buf_index; /* in bytes */ + AVPacket audio_pkt_temp; AVPacket audio_pkt; - uint8_t *audio_pkt_data; - int audio_pkt_size; enum SampleFormat audio_src_fmt; AVAudioConvert *reformat_ctx; @@ -984,11 +984,11 @@ static double get_master_clock(VideoState *is) } /* seek in the stream */ -static void stream_seek(VideoState *is, int64_t pos, int rel) +static void stream_seek(VideoState *is, int64_t pos, int64_t rel) { if (!is->seek_req) { is->seek_pos = pos; - is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0; + is->seek_rel = rel; if (seek_by_bytes) is->seek_flags |= AVSEEK_FLAG_BYTE; is->seek_req = 1; @@ -1226,7 +1226,6 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts) { VideoPicture *vp; int dst_pix_fmt; - AVPicture pict; static struct SwsContext *img_convert_ctx; /* wait until we have space to put a new picture */ @@ -1269,10 +1268,13 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts) /* if the frame is not skipped, then display it */ if (vp->bmp) { + AVPicture pict; + /* 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]; pict.data[2] = vp->bmp->pixels[1]; @@ -1369,9 +1371,9 @@ static int video_thread(void *arg) /* 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_video(is->video_st->codec, + len1 = avcodec_decode_video2(is->video_st->codec, frame, &got_picture, - pkt->data, pkt->size); + pkt); if( (decoder_reorder_pts || pkt->dts == AV_NOPTS_VALUE) && frame->reordered_opaque != AV_NOPTS_VALUE) @@ -1437,9 +1439,9 @@ static int subtitle_thread(void *arg) if (pkt->pts != AV_NOPTS_VALUE) pts = av_q2d(is->subtitle_st->time_base)*pkt->pts; - len1 = avcodec_decode_subtitle(is->subtitle_st->codec, + len1 = avcodec_decode_subtitle2(is->subtitle_st->codec, &sp->sub, &got_subtitle, - pkt->data, pkt->size); + pkt); // if (len1 < 0) // break; if (got_subtitle && sp->sub.format == 0) { @@ -1574,6 +1576,7 @@ static int synchronize_audio(VideoState *is, short *samples, /* decode one audio frame and returns its uncompressed size */ static int audio_decode_frame(VideoState *is, double *pts_ptr) { + AVPacket *pkt_temp = &is->audio_pkt_temp; AVPacket *pkt = &is->audio_pkt; AVCodecContext *dec= is->audio_st->codec; int n, len1, data_size; @@ -1581,19 +1584,19 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) for(;;) { /* NOTE: the audio packet can contain several frames */ - while (is->audio_pkt_size > 0) { + while (pkt_temp->size > 0) { data_size = sizeof(is->audio_buf1); - len1 = avcodec_decode_audio2(dec, + len1 = avcodec_decode_audio3(dec, (int16_t *)is->audio_buf1, &data_size, - is->audio_pkt_data, is->audio_pkt_size); + pkt_temp); if (len1 < 0) { /* if error, we skip the frame */ - is->audio_pkt_size = 0; + pkt_temp->size = 0; break; } - is->audio_pkt_data += len1; - is->audio_pkt_size -= len1; + pkt_temp->data += len1; + pkt_temp->size -= len1; if (data_size <= 0) continue; @@ -1663,8 +1666,8 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) continue; } - is->audio_pkt_data = pkt->data; - is->audio_pkt_size = pkt->size; + pkt_temp->data = pkt->data; + pkt_temp->size = pkt->size; /* if update the audio clock with the pts */ if (pkt->pts != AV_NOPTS_VALUE) { @@ -1752,7 +1755,7 @@ static int stream_component_open(VideoState *is, int stream_index) enc->error_recognition= error_recognition; enc->error_concealment= error_concealment; - set_context_opts(enc, avctx_opts[enc->codec_type], 0); + set_context_opts(enc, avcodec_opts[enc->codec_type], 0); if (!codec || avcodec_open(enc, codec) < 0) @@ -1894,22 +1897,9 @@ static void stream_component_close(VideoState *is, int stream_index) static void dump_stream_info(const AVFormatContext *s) { - if (s->track != 0) - fprintf(stderr, "Track: %d\n", s->track); - if (s->title[0] != '\0') - fprintf(stderr, "Title: %s\n", s->title); - if (s->author[0] != '\0') - fprintf(stderr, "Author: %s\n", s->author); - if (s->copyright[0] != '\0') - fprintf(stderr, "Copyright: %s\n", s->copyright); - if (s->comment[0] != '\0') - fprintf(stderr, "Comment: %s\n", s->comment); - if (s->album[0] != '\0') - fprintf(stderr, "Album: %s\n", s->album); - if (s->year != 0) - fprintf(stderr, "Year: %d\n", s->year); - if (s->genre[0] != '\0') - fprintf(stderr, "Genre: %s\n", s->genre); + AVMetadataTag *tag = NULL; + while ((tag=av_metadata_get(s->metadata,"",tag,AV_METADATA_IGNORE_SUFFIX))) + fprintf(stderr, "%s: %s\n", tag->key, tag->value); } /* since we have only one decoding thread, we can use a global @@ -1929,6 +1919,7 @@ static int decode_thread(void *arg) int err, i, ret, video_index, audio_index, subtitle_index; AVPacket pkt1, *pkt = &pkt1; AVFormatParameters params, *ap = ¶ms; + int eof=0; video_index = -1; audio_index = -1; @@ -1975,7 +1966,7 @@ static int decode_thread(void *arg) /* add the stream start time */ if (ic->start_time != AV_NOPTS_VALUE) timestamp += ic->start_time; - ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD); + ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0); if (ret < 0) { fprintf(stderr, "%s: could not seek to position %0.3f\n", is->filename, (double)timestamp / AV_TIME_BASE); @@ -1987,16 +1978,15 @@ static int decode_thread(void *arg) ic->streams[i]->discard = AVDISCARD_ALL; switch(enc->codec_type) { case CODEC_TYPE_AUDIO: - if ((audio_index < 0 || wanted_audio_stream-- > 0) && !audio_disable) + if (wanted_audio_stream-- >= 0 && !audio_disable) audio_index = i; break; case CODEC_TYPE_VIDEO: - if ((video_index < 0 || wanted_video_stream-- > 0) && !video_disable) + if (wanted_video_stream-- >= 0 && !video_disable) video_index = i; break; case CODEC_TYPE_SUBTITLE: - if (wanted_subtitle_stream >= 0 && !video_disable && - (subtitle_index < 0 || wanted_subtitle_stream-- > 0)) + if (wanted_subtitle_stream-- >= 0 && !video_disable) subtitle_index = i; break; default: @@ -2049,18 +2039,13 @@ static int decode_thread(void *arg) } #endif if (is->seek_req) { - int stream_index= -1; int64_t seek_target= is->seek_pos; + int64_t seek_min= is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN; + int64_t seek_max= is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX; +//FIXME the +-2 is due to rounding being not done in the correct direction in generation +// of the seek_pos/seek_rel variables - if (is-> video_stream >= 0) stream_index= is-> video_stream; - else if(is-> audio_stream >= 0) stream_index= is-> audio_stream; - else if(is->subtitle_stream >= 0) stream_index= is->subtitle_stream; - - if(stream_index>=0){ - seek_target= av_rescale_q(seek_target, AV_TIME_BASE_Q, ic->streams[stream_index]->time_base); - } - - ret = av_seek_frame(is->ic, stream_index, seek_target, is->seek_flags); + ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags); if (ret < 0) { fprintf(stderr, "%s: error while seeking\n", is->ic->filename); }else{ @@ -2078,6 +2063,7 @@ static int decode_thread(void *arg) } } is->seek_req = 0; + eof= 0; } /* if the queue are full, no need to read more */ @@ -2088,21 +2074,25 @@ static int decode_thread(void *arg) SDL_Delay(10); continue; } - if(url_feof(ic->pb)) { - av_init_packet(pkt); - pkt->data=NULL; - pkt->size=0; - pkt->stream_index= is->video_stream; - packet_queue_put(&is->videoq, pkt); + if(url_feof(ic->pb) || eof) { + if(is->video_stream >= 0){ + av_init_packet(pkt); + pkt->data=NULL; + pkt->size=0; + pkt->stream_index= is->video_stream; + packet_queue_put(&is->videoq, pkt); + } + SDL_Delay(10); continue; } ret = av_read_frame(ic, pkt); if (ret < 0) { - if (ret != AVERROR_EOF && url_ferror(ic->pb) == 0) { - SDL_Delay(100); /* wait for user event */ - continue; - } else + if (ret == AVERROR_EOF) + eof=1; + if (url_ferror(ic->pb)) break; + SDL_Delay(100); /* wait for user event */ + continue; } if (pkt->stream_index == is->audio_stream) { packet_queue_put(&is->audioq, pkt); @@ -2360,7 +2350,7 @@ static void event_loop(void) } else { pos = get_master_clock(cur_stream); pos += incr; - stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr); + stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE)); } } break; @@ -2503,9 +2493,9 @@ static const OptionDef options[] = { { "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" }, - { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_audio_stream}, "", "" }, - { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_video_stream}, "", "" }, - { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_subtitle_stream}, "", "" }, + { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_audio_stream}, "select desired audio stream", "stream_number" }, + { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_video_stream}, "select desired video stream", "stream_number" }, + { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_subtitle_stream}, "select desired subtitle stream", "stream_number" }, { "ss", HAS_ARG | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" }, { "bytes", OPT_BOOL, {(void*)&seek_by_bytes}, "seek by bytes" }, { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" }, @@ -2572,7 +2562,7 @@ int main(int argc, char **argv) av_register_all(); for(i=0; i