diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2011-07-14 02:22:48 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-07-14 02:24:10 +0200 |
commit | 80e4fe4063001d0cf468d5f4c7c02ba5b04484b7 (patch) | |
tree | ab237b4967339905110c59f6a118bfda9a5a5433 | |
parent | 6b61920ab76dc6d85ef462909951923935dd643f (diff) | |
parent | b5849f77095439e994b11c25e6063d443b36c228 (diff) | |
download | ffmpeg-80e4fe4063001d0cf468d5f4c7c02ba5b04484b7.tar.gz |
Merge commit 'b5849f77095439e994b11c25e6063d443b36c228'
* commit 'b5849f77095439e994b11c25e6063d443b36c228': (21 commits)
ac3enc: merge AC3MDCTContext with AC3EncodeContext.
ac3enc: prefer passing AC3EncodeContext rather than AVCodecContext
ac3enc: fix memleak
mpeg1video: add CODEC_CAP_SLICE_THREADS.
lavf: fix segfault in av_open_input_stream()
mpegtsenc: set Random Access indicator on keyframe start packets
lavf: Cleanup try_decode_frame() logic.
Replace some gotos that lead to single return statements by direct return.
build: move tests/seek_test.c to libavformat and reuse generic build rules
mxfenc: include needed header for ff_iso8601_to_unix_time() prototype
Add a check for strptime().
lavf: factor out conversion of ISO8601 string to unix time
wav: parse 'bext' metadata
wav: keep parsing until EOF if the input is seekable and we know the size of the data tag
wav: Refactor the tag checking into a switch statement
wav: make sure neither data_size nor sample_count is negative.
wav: refactor the 'fmt ' tag search and parsing.
wav: add an option for writing BEXT chunk
ffmpeg: get rid of a pointless limit on number of streams.
ffmpeg: remove an unused define.
...
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Changelog | 1 | ||||
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | doc/general.texi | 1 | ||||
-rw-r--r-- | ffmpeg.c | 16 | ||||
-rw-r--r-- | ffplay.c | 15 | ||||
-rw-r--r-- | ffserver.c | 6 | ||||
-rw-r--r-- | libavcodec/ac3enc.c | 33 | ||||
-rw-r--r-- | libavcodec/ac3enc.h | 23 | ||||
-rw-r--r-- | libavcodec/ac3enc_fixed.c | 11 | ||||
-rw-r--r-- | libavcodec/ac3enc_float.c | 17 | ||||
-rw-r--r-- | libavcodec/ac3enc_template.c | 8 | ||||
-rw-r--r-- | libavcodec/mpeg12.c | 2 | ||||
-rw-r--r-- | libavformat/Makefile | 2 | ||||
-rw-r--r-- | libavformat/dvenc.c | 7 | ||||
-rw-r--r-- | libavformat/gxfenc.c | 8 | ||||
-rw-r--r-- | libavformat/internal.h | 5 | ||||
-rw-r--r-- | libavformat/movenc.c | 7 | ||||
-rw-r--r-- | libavformat/mpc.c | 16 | ||||
-rw-r--r-- | libavformat/mpegtsenc.c | 67 | ||||
-rw-r--r-- | libavformat/mxfenc.c | 8 | ||||
-rw-r--r-- | libavformat/utils.c | 25 | ||||
-rw-r--r-- | libavformat/wav.c | 87 | ||||
-rw-r--r-- | tests/Makefile | 6 | ||||
-rwxr-xr-x | tests/fate-run.sh | 2 | ||||
-rw-r--r-- | tests/ref/lavf/ts | 2 | ||||
-rw-r--r-- | tests/seek_test.c | 133 |
27 files changed, 252 insertions, 259 deletions
diff --git a/.gitignore b/.gitignore index c922b8855d..dd81f54e4e 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,6 @@ tests/audiogen tests/base64 tests/data tests/rotozoom -tests/seek_test tests/tiny_psnr tests/videogen tests/vsynth1 @@ -5,6 +5,7 @@ version next: - openal input device added - boxblur filter added +- BWF muxer version 0.8: @@ -1110,6 +1110,7 @@ HAVE_LIST=" poll_h setrlimit strerror_r + strptime strtok_r struct_addrinfo struct_ipv6_mreq @@ -2812,6 +2813,7 @@ check_func mmap check_func ${malloc_prefix}posix_memalign && enable posix_memalign check_func setrlimit check_func strerror_r +check_func strptime check_func strtok_r check_func_headers conio.h kbhit check_func_headers io.h setmode diff --git a/doc/general.texi b/doc/general.texi index a52ce69a13..bd17f9056f 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -66,6 +66,7 @@ library: @tab Used in Z and Z95 games. @item Brute Force & Ignorance @tab @tab X @tab Used in the game Flash Traffic: City of Angels. +@item BWF @tab X @tab X @item Interplay C93 @tab @tab X @tab Used in the game Cyberia from Interplay. @item Delphine Software International CIN @tab @tab X @@ -115,7 +115,6 @@ static const OptionDef options[]; #define MAX_FILES 100 #define MAX_STREAMS 1024 /* arbitrary sanity check value */ - static const char *last_asked_format = NULL; static double *ts_scale; static int nb_ts_scale; @@ -1575,7 +1574,7 @@ static int output_packet(InputStream *ist, int ist_index, ret = avcodec_decode_audio3(ist->st->codec, samples, &decoded_data_size, &avpkt); if (ret < 0) - goto fail_decode; + return ret; avpkt.data += ret; avpkt.size -= ret; data_size = ret; @@ -1602,7 +1601,7 @@ static int output_packet(InputStream *ist, int ist_index, &picture, &got_output, &avpkt); quality = same_quality ? picture.quality : 0; if (ret < 0) - goto fail_decode; + return ret; if (!got_output) { /* no picture yet */ goto discard_packet; @@ -1622,7 +1621,7 @@ static int output_packet(InputStream *ist, int ist_index, ret = avcodec_decode_subtitle2(ist->st->codec, &subtitle, &got_output, &avpkt); if (ret < 0) - goto fail_decode; + return ret; if (!got_output) { goto discard_packet; } @@ -1630,7 +1629,7 @@ static int output_packet(InputStream *ist, int ist_index, avpkt.size = 0; break; default: - goto fail_decode; + return -1; } } else { switch(ist->st->codec->codec_type) { @@ -1910,8 +1909,6 @@ static int output_packet(InputStream *ist, int ist_index, } return 0; - fail_decode: - return -1; } static void print_sdp(AVFormatContext **avc, int n) @@ -3197,9 +3194,6 @@ static int opt_input_ts_scale(const char *opt, const char *arg) p++; scale= strtod(p, &p); - if(stream >= MAX_STREAMS) - ffmpeg_exit(1); - ts_scale = grow_array(ts_scale, sizeof(*ts_scale), &nb_ts_scale, stream + 1); ts_scale[stream] = scale; return 0; @@ -3851,7 +3845,7 @@ static int opt_streamid(const char *opt, const char *arg) ffmpeg_exit(1); } *p++ = '\0'; - idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1); + idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, INT_MAX); streamid_map = grow_array(streamid_map, sizeof(*streamid_map), &nb_streamid_map, idx+1); streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX); return 0; @@ -1690,10 +1690,10 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c if ((ret = avfilter_graph_create_filter(&filt_src, &input_filter, "src", NULL, is, graph)) < 0) - goto the_end; + return ret; if ((ret = avfilter_graph_create_filter(&filt_out, avfilter_get_by_name("buffersink"), "out", NULL, pix_fmts, graph)) < 0) - goto the_end; + return ret; if(vfilters) { AVFilterInOut *outputs = avfilter_inout_alloc(); @@ -1710,18 +1710,18 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c inputs->next = NULL; if ((ret = avfilter_graph_parse(graph, vfilters, &inputs, &outputs, NULL)) < 0) - goto the_end; + return ret; av_freep(&vfilters); } else { if ((ret = avfilter_link(filt_src, 0, filt_out, 0)) < 0) - goto the_end; + return ret; } if ((ret = avfilter_graph_config(graph, NULL)) < 0) - goto the_end; + return ret; is->out_video_filter = filt_out; -the_end: + return ret; } @@ -1829,7 +1829,7 @@ static int subtitle_thread(void *arg) SDL_UnlockMutex(is->subpq_mutex); if (is->subtitleq.abort_request) - goto the_end; + return 0; sp = &is->subpq[is->subpq_windex]; @@ -1866,7 +1866,6 @@ static int subtitle_thread(void *arg) } av_free_packet(pkt); } - the_end: return 0; } diff --git a/ffserver.c b/ffserver.c index 10da70bd91..a99e375e67 100644 --- a/ffserver.c +++ b/ffserver.c @@ -3508,7 +3508,7 @@ static int add_av_stream(FFStream *feed, AVStream *st) case AVMEDIA_TYPE_AUDIO: if (av1->channels == av->channels && av1->sample_rate == av->sample_rate) - goto found; + return i; break; case AVMEDIA_TYPE_VIDEO: if (av1->width == av->width && @@ -3516,7 +3516,7 @@ static int add_av_stream(FFStream *feed, AVStream *st) av1->time_base.den == av->time_base.den && av1->time_base.num == av->time_base.num && av1->gop_size == av->gop_size) - goto found; + return i; break; default: abort(); @@ -3528,8 +3528,6 @@ static int add_av_stream(FFStream *feed, AVStream *st) if (!fst) return -1; return feed->nb_streams - 1; - found: - return i; } static void remove_stream(FFStream *stream) diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index 9b0ee2d335..c90554e689 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -1535,10 +1535,10 @@ void ff_ac3_output_frame(AC3EncodeContext *s, unsigned char *frame) } -static void dprint_options(AVCodecContext *avctx) +static void dprint_options(AC3EncodeContext *s) { #ifdef DEBUG - AC3EncodeContext *s = avctx->priv_data; + AVCodecContext *avctx = s->avctx; AC3EncOptions *opt = &s->options; char strbuf[32]; @@ -1689,9 +1689,9 @@ static void validate_mix_level(void *log_ctx, const char *opt_name, * Validate metadata options as set by AVOption system. * These values can optionally be changed per-frame. */ -int ff_ac3_validate_metadata(AVCodecContext *avctx) +int ff_ac3_validate_metadata(AC3EncodeContext *s) { - AC3EncodeContext *s = avctx->priv_data; + AVCodecContext *avctx = s->avctx; AC3EncOptions *opt = &s->options; /* validate mixing levels */ @@ -1820,6 +1820,8 @@ av_cold int ff_ac3_encode_close(AVCodecContext *avctx) av_freep(&s->band_psd_buffer); av_freep(&s->mask_buffer); av_freep(&s->qmant_buffer); + av_freep(&s->cpl_coord_exp_buffer); + av_freep(&s->cpl_coord_mant_buffer); for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { AC3Block *block = &s->blocks[blk]; av_freep(&block->mdct_coef); @@ -1830,10 +1832,11 @@ av_cold int ff_ac3_encode_close(AVCodecContext *avctx) av_freep(&block->band_psd); av_freep(&block->mask); av_freep(&block->qmant); + av_freep(&block->cpl_coord_exp); + av_freep(&block->cpl_coord_mant); } - s->mdct_end(s->mdct); - av_freep(&s->mdct); + s->mdct_end(s); av_freep(&avctx->coded_frame); return 0; @@ -1888,8 +1891,9 @@ static av_cold int set_channel_info(AC3EncodeContext *s, int channels, } -static av_cold int validate_options(AVCodecContext *avctx, AC3EncodeContext *s) +static av_cold int validate_options(AC3EncodeContext *s) { + AVCodecContext *avctx = s->avctx; int i, ret, max_sr; /* validate channel layout */ @@ -1994,7 +1998,7 @@ static av_cold int validate_options(AVCodecContext *avctx, AC3EncodeContext *s) } if (!s->eac3) { - ret = ff_ac3_validate_metadata(avctx); + ret = ff_ac3_validate_metadata(s); if (ret) return ret; } @@ -2081,10 +2085,10 @@ static av_cold void set_bandwidth(AC3EncodeContext *s) } -static av_cold int allocate_buffers(AVCodecContext *avctx) +static av_cold int allocate_buffers(AC3EncodeContext *s) { + AVCodecContext *avctx = s->avctx; int blk, ch; - AC3EncodeContext *s = avctx->priv_data; int channels = s->channels + 1; /* includes coupling channel */ if (s->allocate_sample_buffers(s)) @@ -2197,7 +2201,7 @@ av_cold int ff_ac3_encode_init(AVCodecContext *avctx) ff_ac3_common_init(); - ret = validate_options(avctx, s); + ret = validate_options(s); if (ret) return ret; @@ -2237,12 +2241,11 @@ av_cold int ff_ac3_encode_init(AVCodecContext *avctx) bit_alloc_init(s); - FF_ALLOCZ_OR_GOTO(avctx, s->mdct, sizeof(AC3MDCTContext), init_fail); - ret = s->mdct_init(avctx, s->mdct, 9); + ret = s->mdct_init(s); if (ret) goto init_fail; - ret = allocate_buffers(avctx); + ret = allocate_buffers(s); if (ret) goto init_fail; @@ -2251,7 +2254,7 @@ av_cold int ff_ac3_encode_init(AVCodecContext *avctx) dsputil_init(&s->dsp, avctx); ff_ac3dsp_init(&s->ac3dsp, avctx->flags & CODEC_FLAG_BITEXACT); - dprint_options(avctx); + dprint_options(s); return 0; init_fail: diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h index be2767ad8c..e3b4ba3133 100644 --- a/libavcodec/ac3enc.h +++ b/libavcodec/ac3enc.h @@ -66,10 +66,6 @@ typedef int64_t CoefSumType; #endif -typedef struct AC3MDCTContext { - const SampleType *window; ///< MDCT window function - FFTContext fft; ///< FFT context for MDCT calculation -} AC3MDCTContext; #if 0 /** * Encoding Options used by AVOption. @@ -143,7 +139,8 @@ typedef struct AC3EncodeContext { PutBitContext pb; ///< bitstream writer context DSPContext dsp; AC3DSPContext ac3dsp; ///< AC-3 optimized functions - AC3MDCTContext *mdct; ///< MDCT context + FFTContext mdct; ///< FFT context for MDCT calculation + const SampleType *mdct_window; ///< MDCT window function array AC3Block blocks[AC3_MAX_BLOCKS]; ///< per-block info @@ -226,8 +223,8 @@ typedef struct AC3EncodeContext { int ref_bap_set; ///< indicates if ref_bap pointers have been set /* fixed vs. float function pointers */ - void (*mdct_end)(AC3MDCTContext *mdct); - int (*mdct_init)(AVCodecContext *avctx, AC3MDCTContext *mdct, int nbits); + void (*mdct_end)(struct AC3EncodeContext *s); + int (*mdct_init)(struct AC3EncodeContext *s); /* fixed vs. float templated function pointers */ int (*allocate_sample_buffers)(struct AC3EncodeContext *s); @@ -241,7 +238,7 @@ int ff_ac3_encode_init(AVCodecContext *avctx); int ff_ac3_encode_close(AVCodecContext *avctx); -int ff_ac3_validate_metadata(AVCodecContext *avctx); +int ff_ac3_validate_metadata(AC3EncodeContext *s); void ff_ac3_adjust_frame_size(AC3EncodeContext *s); @@ -260,13 +257,11 @@ void ff_ac3_output_frame(AC3EncodeContext *s, unsigned char *frame); /* prototypes for functions in ac3enc_fixed.c and ac3enc_float.c */ -void ff_ac3_fixed_mdct_end(AC3MDCTContext *mdct); -void ff_ac3_float_mdct_end(AC3MDCTContext *mdct); +void ff_ac3_fixed_mdct_end(AC3EncodeContext *s); +void ff_ac3_float_mdct_end(AC3EncodeContext *s); -int ff_ac3_fixed_mdct_init(AVCodecContext *avctx, AC3MDCTContext *mdct, - int nbits); -int ff_ac3_float_mdct_init(AVCodecContext *avctx, AC3MDCTContext *mdct, - int nbits); +int ff_ac3_fixed_mdct_init(AC3EncodeContext *s); +int ff_ac3_float_mdct_init(AC3EncodeContext *s); /* prototypes for functions in ac3enc_template.c */ diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c index cbe92e1d8d..e7dff757b8 100644 --- a/libavcodec/ac3enc_fixed.c +++ b/libavcodec/ac3enc_fixed.c @@ -41,9 +41,9 @@ static AVClass ac3enc_class = { "Fixed-Point AC-3 Encoder", av_default_item_name /** * Finalize MDCT and free allocated memory. */ -av_cold void AC3_NAME(mdct_end)(AC3MDCTContext *mdct) +av_cold void AC3_NAME(mdct_end)(AC3EncodeContext *s) { - ff_mdct_end(&mdct->fft); + ff_mdct_end(&s->mdct); } @@ -51,11 +51,10 @@ av_cold void AC3_NAME(mdct_end)(AC3MDCTContext *mdct) * Initialize MDCT tables. * @param nbits log2(MDCT size) */ -av_cold int AC3_NAME(mdct_init)(AVCodecContext *avctx, AC3MDCTContext *mdct, - int nbits) +av_cold int AC3_NAME(mdct_init)(AC3EncodeContext *s) { - int ret = ff_mdct_init(&mdct->fft, nbits, 0, -1.0); - mdct->window = ff_ac3_window; + int ret = ff_mdct_init(&s->mdct, 9, 0, -1.0); + s->mdct_window = ff_ac3_window; return ret; } diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c index e21b99d9e9..83337530f2 100644 --- a/libavcodec/ac3enc_float.c +++ b/libavcodec/ac3enc_float.c @@ -45,10 +45,10 @@ static AVClass ac3enc_class = { "AC-3 Encoder", av_default_item_name, /** * Finalize MDCT and free allocated memory. */ -av_cold void ff_ac3_float_mdct_end(AC3MDCTContext *mdct) +av_cold void ff_ac3_float_mdct_end(AC3EncodeContext *s) { - ff_mdct_end(&mdct->fft); - av_freep(&mdct->window); + ff_mdct_end(&s->mdct); + av_freep(&s->mdct_window); } @@ -56,26 +56,25 @@ av_cold void ff_ac3_float_mdct_end(AC3MDCTContext *mdct) * Initialize MDCT tables. * @param nbits log2(MDCT size) */ -av_cold int ff_ac3_float_mdct_init(AVCodecContext *avctx, AC3MDCTContext *mdct, - int nbits) +av_cold int ff_ac3_float_mdct_init(AC3EncodeContext *s) { float *window; int i, n, n2; - n = 1 << nbits; + n = 1 << 9; n2 = n >> 1; window = av_malloc(n * sizeof(*window)); if (!window) { - av_log(avctx, AV_LOG_ERROR, "Cannot allocate memory.\n"); + av_log(s->avctx, AV_LOG_ERROR, "Cannot allocate memory.\n"); return AVERROR(ENOMEM); } ff_kbd_window_init(window, 5.0, n2); for (i = 0; i < n2; i++) window[n-1-i] = window[i]; - mdct->window = window; + s->mdct_window = window; - return ff_mdct_init(&mdct->fft, nbits, 0, -2.0 / n); + return ff_mdct_init(&s->mdct, 9, 0, -2.0 / n); } diff --git a/libavcodec/ac3enc_template.c b/libavcodec/ac3enc_template.c index c7243c7644..9b9151b3e0 100644 --- a/libavcodec/ac3enc_template.c +++ b/libavcodec/ac3enc_template.c @@ -108,13 +108,13 @@ static void apply_mdct(AC3EncodeContext *s) const SampleType *input_samples = &s->planar_samples[ch][blk * AC3_BLOCK_SIZE]; apply_window(&s->dsp, s->windowed_samples, input_samples, - s->mdct->window, AC3_WINDOW_SIZE); + s->mdct_window, AC3_WINDOW_SIZE); if (s->fixed_point) block->coeff_shift[ch+1] = normalize_samples(s); - s->mdct->fft.mdct_calcw(&s->mdct->fft, block->mdct_coef[ch+1], - s->windowed_samples); + s->mdct.mdct_calcw(&s->mdct, block->mdct_coef[ch+1], + s->windowed_samples); } } } @@ -424,7 +424,7 @@ int AC3_NAME(encode_frame)(AVCodecContext *avctx, unsigned char *frame, int ret; if (!s->eac3 && s->options.allow_per_frame_metadata) { - ret = ff_ac3_validate_metadata(avctx); + ret = ff_ac3_validate_metadata(s); if (ret) return ret; } diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 87dc0fbbed..20155a0219 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -2577,7 +2577,7 @@ AVCodec ff_mpeg1video_decoder = { NULL, mpeg_decode_end, mpeg_decode_frame, - CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY, + CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY | CODEC_CAP_SLICE_THREADS, .flush= flush, .max_lowres= 3, .long_name= NULL_IF_CONFIG_SMALL("MPEG-1 video"), diff --git a/libavformat/Makefile b/libavformat/Makefile index ce4891bc77..9f5bfb42ad 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -341,7 +341,7 @@ OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o OBJS-$(CONFIG_ALSA_INDEV) += timefilter.o OBJS-$(CONFIG_JACK_INDEV) += timefilter.o -TESTPROGS = timefilter +TESTPROGS = seek timefilter TOOLS = pktdumper probetest include $(SRC_PATH)/subdir.mak diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c index 3b2a8eb711..217ee56b84 100644 --- a/libavformat/dvenc.c +++ b/libavformat/dvenc.c @@ -343,11 +343,8 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s) c->start_time = s->timestamp; else #endif - if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) { - struct tm time = {0}; - strptime(t->value, "%Y - %m - %dT%T", &time); - c->start_time = mktime(&time); - } + if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) + c->start_time = ff_iso8601_to_unix_time(t->value); for (i=0; i < c->n_ast; i++) { if (c->ast[i] && !(c->audio_data[i]=av_fifo_alloc(100*AVCODEC_MAX_AUDIO_FRAME_SIZE))) { diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c index 62ee4eb751..d7c8698b61 100644 --- a/libavformat/gxfenc.c +++ b/libavformat/gxfenc.c @@ -402,12 +402,8 @@ static int gxf_write_umf_material_description(AVFormatContext *s) timestamp = s->timestamp; else #endif - if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) { - struct tm time = {0}; - strptime(t->value, "%Y - %m - %dT%T", &time); - timestamp = mktime(&time); - } - + if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) + timestamp = ff_iso8601_to_unix_time(t->value); // XXX drop frame uint32_t timecode = diff --git a/libavformat/internal.h b/libavformat/internal.h index 7c8eaf258a..72f15d3362 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -246,4 +246,9 @@ void ff_make_absolute_url(char *buf, int size, const char *base, enum CodecID ff_guess_image2_codec(const char *filename); +/** + * Convert a date string in ISO8601 format to Unix timestamp. + */ +int64_t ff_iso8601_to_unix_time(const char *datestr); + #endif /* AVFORMAT_INTERNAL_H */ diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 41c59d49c1..af6d48b801 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -2279,11 +2279,8 @@ static int mov_write_header(AVFormatContext *s) mov->time = s->timestamp; else #endif - if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) { - struct tm time = {0}; - strptime(t->value, "%Y - %m - %dT%T", &time); - mov->time = mktime(&time); - } + if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) + mov->time = ff_iso8601_to_unix_time(t->value); mov->time += 0x7C25B080; //1970 based -> 1904 based if (mov->chapter_track) diff --git a/libavformat/mpc.c b/libavformat/mpc.c index 4d6854f13f..aba73a7d6d 100644 --- a/libavformat/mpc.c +++ b/libavformat/mpc.c @@ -70,7 +70,15 @@ static int mpc_read_header(AVFormatContext *s, AVFormatParameters *ap) av_log(s, AV_LOG_ERROR, "Too many frames, seeking is not possible\n"); return -1; } - c->frames = av_malloc(c->fcount * sizeof(MPCFrame)); + if(c->fcount){ + c->frames = av_malloc(c->fcount * sizeof(MPCFrame)); + if(!c->frames){ + av_log(s, AV_LOG_ERROR, "Cannot allocate seektable\n"); + return AVERROR(ENOMEM); + } + }else{ + av_log(s, AV_LOG_WARNING, "Container reports no frames\n"); + } c->curframe = 0; c->lastframe = -1; c->curbits = 8; @@ -111,7 +119,7 @@ static int mpc_read_packet(AVFormatContext *s, AVPacket *pkt) int ret, size, size2, curbits, cur = c->curframe; int64_t tmp, pos; - if (c->curframe >= c->fcount) + if (c->curframe >= c->fcount && c->fcount) return -1; if(c->curframe != c->lastframe + 1){ @@ -133,7 +141,7 @@ static int mpc_read_packet(AVFormatContext *s, AVPacket *pkt) avio_seek(s->pb, pos, SEEK_SET); size = ((size2 + curbits + 31) & ~31) >> 3; - if(cur == c->frames_noted){ + if(cur == c->frames_noted && c->fcount){ c->frames[cur].pos = pos; c->frames[cur].size = size; c->frames[cur].skip = curbits - 20; @@ -146,7 +154,7 @@ static int mpc_read_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EIO); pkt->data[0] = curbits; - pkt->data[1] = (c->curframe > c->fcount); + pkt->data[1] = (c->curframe > c->fcount) && c->fcount; pkt->data[2] = 0; pkt->data[3] = 0; diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index a7e13e83d5..d1386aa6fa 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -204,6 +204,7 @@ typedef struct MpegTSWriteStream { int first_pts_check; ///< first pts check needed int64_t payload_pts; int64_t payload_dts; + int payload_flags; uint8_t payload[DEFAULT_PES_PAYLOAD_SIZE]; ADTSContext *adts; } MpegTSWriteStream; @@ -621,7 +622,7 @@ static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb) ts->first_pcr; } -static uint8_t* write_pcr_bits(uint8_t *buf, int64_t pcr) +static int write_pcr_bits(uint8_t *buf, int64_t pcr) { int64_t pcr_low = pcr % 300, pcr_high = pcr / 300; @@ -632,7 +633,7 @@ static uint8_t* write_pcr_bits(uint8_t *buf, int64_t pcr) *buf++ = pcr_high << 7 | pcr_low >> 8 | 0x7e; *buf++ = pcr_low; - return buf; + return 6; } /* Write a single null transport stream packet */ @@ -668,7 +669,7 @@ static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st) *q++ = 0x10; /* Adaptation flags: PCR present */ /* PCR coded into 6 bytes */ - q = write_pcr_bits(q, get_pcr(ts, s->pb)); + q += write_pcr_bits(q, get_pcr(ts, s->pb)); /* stuffing bytes */ memset(q, 0xFF, TS_PACKET_SIZE - (q - buf)); @@ -689,6 +690,39 @@ static void write_pts(uint8_t *q, int fourbits, int64_t pts) *q++ = val; } +/* Set an adaptation field flag in an MPEG-TS packet*/ +static void set_af_flag(uint8_t *pkt, int flag) +{ + // expect at least one flag to set + assert(flag); + + if ((pkt[3] & 0x20) == 0) { + // no AF yet, set adaptation field flag + pkt[3] |= 0x20; + // 1 byte length, no flags + pkt[4] = 1; + pkt[5] = 0; + } + pkt[5] |= flag; +} + +/* Extend the adaptation field by size bytes */ +static void extend_af(uint8_t *pkt, int size) +{ + // expect already existing adaptation field + assert(pkt[3] & 0x20); + pkt[4] += size; +} + +/* Get a pointer to MPEG-TS payload (right after TS packet header) */ +static uint8_t *get_ts_payload_start(uint8_t *pkt) +{ + if (pkt[3] & 0x20) + return pkt + 5 + pkt[4]; + else + return pkt + 4; +} + /* Add a pes header to the front of payload, and segment into an integer number of * ts packets. The final ts packet is padded using an over-sized adaptation header * to exactly fill the last ts packet. @@ -696,7 +730,7 @@ static void write_pts(uint8_t *q, int fourbits, int64_t pts) */ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, const uint8_t *payload, int payload_size, - int64_t pts, int64_t dts) + int64_t pts, int64_t dts, int key) { MpegTSWriteStream *ts_st = st->priv_data; MpegTSWrite *ts = s->priv_data; @@ -741,8 +775,17 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, *q++ = val; *q++ = ts_st->pid; ts_st->cc = (ts_st->cc + 1) & 0xf; - *q++ = 0x10 | ts_st->cc | (write_pcr ? 0x20 : 0); + *q++ = 0x10 | ts_st->cc; // payload indicator + CC + if (key && is_start && pts != AV_NOPTS_VALUE) { + // set Random Access for key frames + if (ts_st->pid == ts_st->service->pcr_pid) + write_pcr = 1; + set_af_flag(buf, 0x40); + q = get_ts_payload_start(buf); + } if (write_pcr) { + set_af_flag(buf, 0x10); + q = get_ts_payload_start(buf); // add 11, pcr references the last byte of program clock reference base if (ts->mux_rate > 1) pcr = get_pcr(ts, s->pb); @@ -750,9 +793,8 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, pcr = (dts - delay)*300; if (dts != AV_NOPTS_VALUE && dts < pcr / 300) av_log(s, AV_LOG_WARNING, "dts < pcr, TS is invalid\n"); - *q++ = 7; /* AFC length */ - *q++ = 0x10; /* flags: PCR present */ - q = write_pcr_bits(q, pcr); + extend_af(buf, write_pcr_bits(q, pcr)); + q = get_ts_payload_start(buf); } if (is_start) { int pes_extension = 0; @@ -950,20 +992,22 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt) if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) { // for video and subtitle, write a single pes packet - mpegts_write_pes(s, st, buf, size, pts, dts); + mpegts_write_pes(s, st, buf, size, pts, dts, pkt->flags & AV_PKT_FLAG_KEY); av_free(data); return 0; } if (ts_st->payload_index + size > DEFAULT_PES_PAYLOAD_SIZE) { mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index, - ts_st->payload_pts, ts_st->payload_dts); + ts_st->payload_pts, ts_st->payload_dts, + ts_st->payload_flags & AV_PKT_FLAG_KEY); ts_st->payload_index = 0; } if (!ts_st->payload_index) { ts_st->payload_pts = pts; ts_st->payload_dts = dts; + ts_st->payload_flags = pkt->flags; } memcpy(ts_st->payload + ts_st->payload_index, buf, size); @@ -988,7 +1032,8 @@ static int mpegts_write_end(AVFormatContext *s) ts_st = st->priv_data; if (ts_st->payload_index > 0) { mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index, - ts_st->payload_pts, ts_st->payload_dts); + ts_st->payload_pts, ts_st->payload_dts, + ts_st->payload_flags & AV_PKT_FLAG_KEY); } av_freep(&ts_st->adts); } diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index ad91c6a2ad..37e5e3d2ca 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -39,6 +39,7 @@ #include "libavcodec/bytestream.h" #include "audiointerleave.h" #include "avformat.h" +#include "internal.h" #include "mxf.h" static const int NTSC_samples_per_frame[] = { 1602, 1601, 1602, 1601, 1602, 0 }; @@ -1519,11 +1520,8 @@ static int mxf_write_header(AVFormatContext *s) timestamp = s->timestamp; else #endif - if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) { - struct tm time = {0}; - strptime(t->value, "%Y - %m - %dT%T", &time); - timestamp = mktime(&time); - } + if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) + timestamp = ff_iso8601_to_unix_time(t->value); if (timestamp) mxf->timestamp = mxf_parse_timestamp(timestamp); mxf->duration = -1; diff --git a/libavformat/utils.c b/libavformat/utils.c index b9a4ebab9d..3d949baf24 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -471,7 +471,8 @@ int av_open_input_stream(AVFormatContext **ic_ptr, else ic->pb = pb; - err = avformat_open_input(&ic, filename, fmt, &opts); + if ((err = avformat_open_input(&ic, filename, fmt, &opts)) < 0) + goto fail; ic->pb = ic->pb ? ic->pb : pb; // don't leak custom pb if it wasn't set above *ic_ptr = ic; @@ -2129,7 +2130,8 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option return ret; } - if(!has_codec_parameters(st->codec) || !has_decode_delay_been_guessed(st)){ + if(!has_codec_parameters(st->codec) || !has_decode_delay_been_guessed(st) || + (!st->codec_info_nb_frames && st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF)) { switch(st->codec->codec_type) { case AVMEDIA_TYPE_VIDEO: avcodec_get_frame_defaults(&picture); @@ -2436,11 +2438,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) least one frame of codec data, this makes sure the codec initializes the channel configuration and does not only trust the values from the container. */ - if (!has_codec_parameters(st->codec) || - !has_decode_delay_been_guessed(st) || - (st->codec->codec && - st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF)) - try_decode_frame(st, pkt, (options && i <= orig_nb_streams )? &options[i] : NULL); + try_decode_frame(st, pkt, (options && i <= orig_nb_streams )? &options[i] : NULL); st->codec_info_nb_frames++; count++; @@ -4012,3 +4010,16 @@ void ff_make_absolute_url(char *buf, int size, const char *base, } av_strlcat(buf, rel, size); } + +int64_t ff_iso8601_to_unix_time(const char *datestr) +{ +#if HAVE_STRPTIME + struct tm time = {0}; + strptime(datestr, "%Y - %m - %dT%T", &time); + return mktime(&time); +#else + av_log(NULL, AV_LOG_WARNING, "strptime() unavailable on this system, cannot convert " + "the date string.\n"); + return 0; +#endif +} diff --git a/libavformat/wav.c b/libavformat/wav.c index f09e676ce0..22419ccb4a 100644 --- a/libavformat/wav.c +++ b/libavformat/wav.c @@ -23,23 +23,85 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" #include "libavutil/mathematics.h" +#include "libavutil/opt.h" #include "avformat.h" #include "avio_internal.h" #include "pcm.h" #include "riff.h" +#include "avio.h" +#include "avio_internal.h" #include "metadata.h" typedef struct { + const AVClass *class; int64_t data; int64_t data_end; int64_t minpts; int64_t maxpts; int last_duration; int w64; + int write_bext; } WAVContext; #if CONFIG_WAV_MUXER +static inline void bwf_write_bext_string(AVFormatContext *s, const char *key, int maxlen) +{ + AVDictionaryEntry *tag; + int len = 0; + + if (tag = av_dict_get(s->metadata, key, NULL, 0)) { + len = strlen(tag->value); + len = FFMIN(len, maxlen); + avio_write(s->pb, tag->value, len); + } + + ffio_fill(s->pb, 0, maxlen - len); +} + +static void bwf_write_bext_chunk(AVFormatContext *s) +{ + AVDictionaryEntry *tmp_tag; + uint64_t time_reference = 0; + int64_t bext = ff_start_tag(s->pb, "bext"); + + bwf_write_bext_string(s, "description", 256); + bwf_write_bext_string(s, "originator", 32); + bwf_write_bext_string(s, "originator_reference", 32); + bwf_write_bext_string(s, "origination_date", 10); + bwf_write_bext_string(s, "origination_time", 8); + + if (tmp_tag = av_dict_get(s->metadata, "time_reference", NULL, 0)) + time_reference = strtoll(tmp_tag->value, NULL, 10); + avio_wl64(s->pb, time_reference); + avio_wl16(s->pb, 1); // set version to 1 + + if (tmp_tag = av_dict_get(s->metadata, "umid", NULL, 0)) { + unsigned char umidpart_str[17] = {0}; + int i; + uint64_t umidpart; + int len = strlen(tmp_tag->value+2); + + for (i = 0; i < len/16; i++) { + memcpy(umidpart_str, tmp_tag->value + 2 + (i*16), 16); + umidpart = strtoll(umidpart_str, NULL, 16); + avio_wb64(s->pb, umidpart); + } + ffio_fill(s->pb, 0, 64 - i*8); + } else + ffio_fill(s->pb, 0, 64); // zero UMID + + ffio_fill(s->pb, 0, 190); // Reserved + + if (tmp_tag = av_dict_get(s->metadata, "coding_history", NULL, 0)) + avio_put_str(s->pb, tmp_tag->value); + + ff_end_tag(s->pb, bext); +} + static int wav_write_header(AVFormatContext *s) { WAVContext *wav = s->priv_data; @@ -66,6 +128,9 @@ static int wav_write_header(AVFormatContext *s) ff_end_tag(pb, fact); } + if (wav->write_bext) + bwf_write_bext_chunk(s); + av_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate); wav->maxpts = wav->last_duration = 0; wav->minpts = INT64_MAX; @@ -126,6 +191,20 @@ static int wav_write_trailer(AVFormatContext *s) return 0; } +#define OFFSET(x) offsetof(WAVContext, x) +#define ENC AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "write_bext", "Write BEXT chunk.", OFFSET(write_bext), FF_OPT_TYPE_INT, { 0 }, 0, 1, ENC }, + { NULL }, +}; + +static const AVClass wav_muxer_class = { + .class_name = "WAV muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVOutputFormat ff_wav_muxer = { "wav", NULL_IF_CONFIG_SMALL("WAV format"), @@ -138,6 +217,7 @@ AVOutputFormat ff_wav_muxer = { wav_write_packet, wav_write_trailer, .codec_tag= (const AVCodecTag* const []){ff_codec_wav_tags, 0}, + .priv_class = &wav_muxer_class, }; #endif /* CONFIG_WAV_MUXER */ @@ -207,11 +287,13 @@ static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st) return 0; } -static inline int wav_parse_bext_string(AVFormatContext *s, const char *key, int length) +static inline int wav_parse_bext_string(AVFormatContext *s, const char *key, + int length) { char temp[257]; int ret; + av_assert0(length <= sizeof(temp)); if ((ret = avio_read(s->pb, temp, length)) < 0) return ret; @@ -337,6 +419,7 @@ static int wav_read_header(AVFormatContext *s, return AVERROR_INVALIDDATA; } avio_skip(pb, size - 24); /* skip rest of ds64 chunk */ + } for (;;) { @@ -378,7 +461,7 @@ static int wav_read_header(AVFormatContext *s, goto break_loop; break; case MKTAG('f','a','c','t'): - if(!sample_count) + if (!sample_count) sample_count = avio_rl32(pb); break; case MKTAG('b','e','x','t'): diff --git a/tests/Makefile b/tests/Makefile index 35e803d102..4739446674 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -28,9 +28,6 @@ tests/data/asynth1.sw: tests/audiogen$(HOSTEXESUF) tests/data/asynth1.sw tests/vsynth%/00.pgm: TAG = GEN -tests/seek_test$(EXESUF): tests/seek_test.o $(FF_DEP_LIBS) - $(LD) $(LDFLAGS) -o $@ $< $(FF_EXTRALIBS) - include $(SRC_PATH)/tests/fate.mak include $(SRC_PATH)/tests/fate2.mak @@ -64,7 +61,7 @@ $(filter-out %-aref,$(FATE_ACODEC)): $(AREF) $(filter-out %-vref,$(FATE_VCODEC)): $(VREF) $(FATE_LAVF): $(REFS) $(FATE_LAVFI): $(REFS) tools/lavfi-showfiltfmts$(EXESUF) -$(FATE_SEEK): fate-codec fate-lavf tests/seek_test$(EXESUF) +$(FATE_SEEK): fate-codec fate-lavf libavformat/seek-test$(EXESUF) $(FATE_ACODEC): CMD = codectest acodec $(FATE_VSYNTH1): CMD = codectest vsynth1 @@ -107,7 +104,6 @@ clean:: testclean testclean: $(RM) -r tests/vsynth1 tests/vsynth2 tests/data $(RM) $(CLEANSUFFIXES:%=tests/%) - $(RM) tests/seek_test$(EXESUF) tests/seek_test.o $(RM) $(TESTTOOLS:%=tests/%$(HOSTEXESUF)) -include $(wildcard tests/*.d) diff --git a/tests/fate-run.sh b/tests/fate-run.sh index 10497c497e..4121035853 100755 --- a/tests/fate-run.sh +++ b/tests/fate-run.sh @@ -104,7 +104,7 @@ seektest(){ file=$(echo tests/data/$d/$file) ;; esac - $target_exec $target_path/tests/seek_test $target_path/$file + $target_exec $target_path/libavformat/seek-test $target_path/$file } mkdir -p "$outdir" diff --git a/tests/ref/lavf/ts b/tests/ref/lavf/ts index efac3ad4ee..3b2dad1b5e 100644 --- a/tests/ref/lavf/ts +++ b/tests/ref/lavf/ts @@ -1,3 +1,3 @@ -178f5094fc874112d21b4a8716121d96 *./tests/data/lavf/lavf.ts +151774afed45b19da9b7e83613a1e72b *./tests/data/lavf/lavf.ts 406644 ./tests/data/lavf/lavf.ts ./tests/data/lavf/lavf.ts CRC=0x133216c1 diff --git a/tests/seek_test.c b/tests/seek_test.c deleted file mode 100644 index 76a3e8ccff..0000000000 --- a/tests/seek_test.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2003 Fabrice Bellard - * Copyright (c) 2007 Michael Niedermayer - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <stdint.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "libavutil/common.h" -#include "libavutil/mathematics.h" -#include "libavformat/avformat.h" - -#undef exit -#undef printf -#undef fprintf - -static char buffer[20]; - -static const char *ret_str(int v) -{ - switch (v) { - case AVERROR_EOF: return "-EOF"; - case AVERROR(EIO): return "-EIO"; - case AVERROR(ENOMEM): return "-ENOMEM"; - case AVERROR(EINVAL): return "-EINVAL"; - default: - snprintf(buffer, sizeof(buffer), "%2d", v); - return buffer; - } -} - -static void ts_str(char buffer[60], int64_t ts, AVRational base) -{ - double tsval; - if (ts == AV_NOPTS_VALUE) { - strcpy(buffer, " NOPTS "); - return; - } - tsval = ts * av_q2d(base); - snprintf(buffer, 60, "%9f", tsval); -} - -int main(int argc, char **argv) -{ - const char *filename; - AVFormatContext *ic = NULL; - int i, ret, stream_id; - int64_t timestamp; - AVFormatParameters params, *ap= ¶ms; - memset(ap, 0, sizeof(params)); - ap->channels=1; - ap->sample_rate= 22050; - - /* initialize libavcodec, and register all codecs and formats */ - av_register_all(); - - if (argc != 2) { - printf("usage: %s input_file\n" - "\n", argv[0]); - exit(1); - } - - filename = argv[1]; - - ret = av_open_input_file(&ic, filename, NULL, 0, ap); - if (ret < 0) { - fprintf(stderr, "cannot open %s\n", filename); - exit(1); - } - - ret = av_find_stream_info(ic); - if (ret < 0) { - fprintf(stderr, "%s: could not find codec parameters\n", filename); - exit(1); - } - - for(i=0; ; i++){ - AVPacket pkt; - AVStream *av_uninit(st); - char ts_buf[60]; - - memset(&pkt, 0, sizeof(pkt)); - if(ret>=0){ - ret= av_read_frame(ic, &pkt); - if(ret>=0){ - char dts_buf[60]; - st= ic->streams[pkt.stream_index]; - ts_str(dts_buf, pkt.dts, st->time_base); - ts_str(ts_buf, pkt.pts, st->time_base); - printf("ret:%-10s st:%2d flags:%d dts:%s pts:%s pos:%7" PRId64 " size:%6d", ret_str(ret), pkt.stream_index, pkt.flags, dts_buf, ts_buf, pkt.pos, pkt.size); - av_free_packet(&pkt); - } else - printf("ret:%s", ret_str(ret)); // necessary to avoid trailing whitespace - printf("\n"); - } - - if(i>25) break; - - stream_id= (i>>1)%(ic->nb_streams+1) - 1; - timestamp= (i*19362894167LL) % (4*AV_TIME_BASE) - AV_TIME_BASE; - if(stream_id>=0){ - st= ic->streams[stream_id]; - timestamp= av_rescale_q(timestamp, AV_TIME_BASE_Q, st->time_base); - } - //FIXME fully test the new seek API - if(i&1) ret = avformat_seek_file(ic, stream_id, INT64_MIN, timestamp, timestamp, 0); - else ret = avformat_seek_file(ic, stream_id, timestamp, timestamp, INT64_MAX, 0); - ts_str(ts_buf, timestamp, stream_id < 0 ? AV_TIME_BASE_Q : st->time_base); - printf("ret:%-10s st:%2d flags:%d ts:%s\n", ret_str(ret), stream_id, i&1, ts_buf); - } - - av_close_input_file(ic); - - return 0; -} |