Newer
Older
int64_t last= last_dts[index];
int64_t duration= pkt->dts - last;
if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && duration>0){
double dur= duration * av_q2d(st->time_base);
// if(st->codec->codec_type == CODEC_TYPE_VIDEO)
// av_log(NULL, AV_LOG_ERROR, "%f\n", dur);
if(duration_count[index] < 2)
Baptiste Coudurier
committed
memset(duration_error[index], 0, sizeof(*duration_error));
for(i=1; i<MAX_STD_TIMEBASES; i++){
int framerate= get_std_framerate(i);
int ticks= lrintf(dur*framerate/(1001*12));
double error= dur - ticks*1001*12/(double)framerate;
duration_error[index][i] += error*error;
}
duration_count[index]++;
if(last == AV_NOPTS_VALUE || duration_count[index]<=1)
last_dts[pkt->stream_index]= pkt->dts;
if (st->codec->codec_id == CODEC_ID_NONE) {
AVProbeData *pd = &(probe_data[st->index]);
Wolfram Gloger
committed
pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE);
memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size);
pd->buf_size += pkt->size;
Wolfram Gloger
committed
memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE);
Michael Niedermayer
committed
if(st->parser && st->parser->parser->split && !st->codec->extradata){
int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);
Michael Niedermayer
committed
if(i){
Michael Niedermayer
committed
st->codec->extradata_size= i;
st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
Michael Niedermayer
committed
memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size);
memset(st->codec->extradata + i, 0, FF_INPUT_BUFFER_PADDING_SIZE);
Michael Niedermayer
committed
}
}
/* if still no information, we try to open the codec and to
decompress the frame. We try to avoid that in most cases as
it takes longer and uses more memory. For MPEG-4, we need to
decompress for QuickTime. */
Michael Niedermayer
committed
if (!has_codec_parameters(st->codec) /*&&
(st->codec->codec_id == CODEC_ID_FLV1 ||
st->codec->codec_id == CODEC_ID_H264 ||
st->codec->codec_id == CODEC_ID_H263 ||
st->codec->codec_id == CODEC_ID_H261 ||
st->codec->codec_id == CODEC_ID_VORBIS ||
st->codec->codec_id == CODEC_ID_MJPEG ||
st->codec->codec_id == CODEC_ID_PNG ||
st->codec->codec_id == CODEC_ID_PAM ||
st->codec->codec_id == CODEC_ID_PGM ||
st->codec->codec_id == CODEC_ID_PGMYUV ||
st->codec->codec_id == CODEC_ID_PBM ||
st->codec->codec_id == CODEC_ID_PPM ||
st->codec->codec_id == CODEC_ID_SHORTEN ||
(st->codec->codec_id == CODEC_ID_MPEG4 && !st->need_parsing))*/)
try_decode_frame(st, pkt->data, pkt->size);
if (st->time_base.den > 0 && av_rescale_q(codec_info_duration[st->index], st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) {
Fabrice Bellard
committed
}
count++;
}
Michael Niedermayer
committed
for(i=0;i<ic->nb_streams;i++) {
st = ic->streams[i];
Michael Niedermayer
committed
if(st->codec->codec)
avcodec_close(st->codec);
Michael Niedermayer
committed
}
Fabrice Bellard
committed
for(i=0;i<ic->nb_streams;i++) {
st = ic->streams[i];
Michael Niedermayer
committed
if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_sample)
st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
if(duration_count[i]
&& tb_unreliable(st->codec) /*&&
//FIXME we should not special-case MPEG-2, but this needs testing with non-MPEG-2 ...
st->time_base.num*duration_sum[i]/duration_count[i]*101LL > st->time_base.den*/){
double best_error= 2*av_q2d(st->time_base);
best_error= best_error*best_error*duration_count[i]*1000*12*30;
for(j=1; j<MAX_STD_TIMEBASES; j++){
double error= duration_error[i][j] * get_std_framerate(j);
// if(st->codec->codec_type == CODEC_TYPE_VIDEO)
// av_log(NULL, AV_LOG_ERROR, "%f %f\n", get_std_framerate(j) / 12.0/1001, error);
if(error < best_error){
best_error= error;
av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, get_std_framerate(j), 12*1001, INT_MAX);
if( st->codec->time_base.den * (int64_t)st->time_base.num
<= st->codec->time_base.num * (int64_t)st->time_base.den){
st->r_frame_rate.num = st->codec->time_base.den;
st->r_frame_rate.den = st->codec->time_base.num;
}else{
st->r_frame_rate.num = st->time_base.den;
st->r_frame_rate.den = st->time_base.num;
}
Michael Niedermayer
committed
}
}else if(st->codec->codec_type == CODEC_TYPE_AUDIO) {
if (st->codec->codec_id == CODEC_ID_NONE && probe_data[st->index].buf_size > 0) {
codec_identified[st->index] = set_codec_from_probe_data(st, &(probe_data[st->index]), 1);
if(!st->codec->bits_per_sample)
st->codec->bits_per_sample= av_get_bits_per_sample(st->codec->codec_id);
Fabrice Bellard
committed
}
Fabrice Bellard
committed
av_estimate_timings(ic, old_offset);
for(i=0;i<ic->nb_streams;i++) {
st = ic->streams[i];
if (codec_identified[st->index])
break;
}
//FIXME this is a mess
if(i!=ic->nb_streams){
av_read_frame_flush(ic);
for(i=0;i<ic->nb_streams;i++) {
st = ic->streams[i];
if (codec_identified[st->index]) {
av_seek_frame(ic, st->index, 0.0, 0);
}
st->cur_dts= st->first_dts;
url_fseek(ic->pb, ic->data_offset, SEEK_SET);
Aurelien Jacobs
committed
compute_chapters_end(ic);
/* correct DTS for B-frame streams with no timestamps */
for(i=0;i<ic->nb_streams;i++) {
st = ic->streams[i];
Michael Niedermayer
committed
if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
if(b-frames){
ppktl = &ic->packet_buffer;
while(ppkt1){
if(ppkt1->stream_index != i)
continue;
if(ppkt1->pkt->dts < 0)
break;
if(ppkt1->pkt->pts != AV_NOPTS_VALUE)
break;
ppkt1->pkt->dts -= delta;
ppkt1= ppkt1->next;
}
if(ppkt1)
continue;
st->cur_dts -= delta;
}
}
}
#endif
av_free(duration_error);
for(i=0;i<MAX_STREAMS;i++){
av_freep(&(probe_data[i].buf));
}
Fabrice Bellard
committed
return ret;
/*******************************************************/
int av_read_play(AVFormatContext *s)
{
Björn Axelsson
committed
if (s->iformat->read_play)
return s->iformat->read_play(s);
return av_url_read_fpause(s->pb, 0);
Björn Axelsson
committed
return AVERROR(ENOSYS);
}
int av_read_pause(AVFormatContext *s)
{
Björn Axelsson
committed
if (s->iformat->read_pause)
return s->iformat->read_pause(s);
return av_url_read_fpause(s->pb, 1);
Björn Axelsson
committed
return AVERROR(ENOSYS);
void av_close_input_stream(AVFormatContext *s)
int i;
AVStream *st;
/* free previous packet */
if (s->cur_st && s->cur_st->parser)
av_free_packet(&s->cur_pkt);
Fabrice Bellard
committed
if (s->iformat->read_close)
s->iformat->read_close(s);
/* free all data in a stream component */
st = s->streams[i];
if (st->parser) {
av_parser_close(st->parser);
av_free(st->index_entries);
av_free(st->codec->extradata);
Michael Niedermayer
committed
av_free(st->codec);
av_free(st->priv_data);
Nico Sabbi
committed
for(i=s->nb_programs-1; i>=0; i--) {
av_freep(&s->programs[i]->provider_name);
av_freep(&s->programs[i]->name);
av_freep(&s->programs[i]->stream_index);
Nico Sabbi
committed
av_freep(&s->programs[i]);
}
flush_packet_queue(s);
Philip Gladstone
committed
av_freep(&s->priv_data);
Michael Niedermayer
committed
while(s->nb_chapters--) {
av_free(s->chapters[s->nb_chapters]->title);
av_free(s->chapters[s->nb_chapters]);
}
av_freep(&s->chapters);
void av_close_input_file(AVFormatContext *s)
{
ByteIOContext *pb = s->iformat->flags & AVFMT_NOFILE ? NULL : s->pb;
av_close_input_stream(s);
if (pb)
url_fclose(pb);
}
Fabrice Bellard
committed
AVStream *av_new_stream(AVFormatContext *s, int id)
{
AVStream *st;
int i;
Fabrice Bellard
committed
if (s->nb_streams >= MAX_STREAMS)
return NULL;
st = av_mallocz(sizeof(AVStream));
if (!st)
return NULL;
Michael Niedermayer
committed
st->codec= avcodec_alloc_context();
if (s->iformat) {
/* no default bitrate if decoding */
Michael Niedermayer
committed
st->codec->bit_rate = 0;
Fabrice Bellard
committed
st->index = s->nb_streams;
st->id = id;
Fabrice Bellard
committed
st->start_time = AV_NOPTS_VALUE;
st->duration = AV_NOPTS_VALUE;
Michael Niedermayer
committed
/* we set the current DTS to 0 so that formats without any timestamps
but durations get some timestamps, formats with some unknown
timestamps have their first few packets buffered and the
timestamps corrected before they are returned to the user */
st->cur_dts = 0;
st->first_dts = AV_NOPTS_VALUE;
av_set_pts_info(st, 33, 1, 90000);
for(i=0; i<MAX_REORDER_DELAY+1; i++)
st->pts_buffer[i]= AV_NOPTS_VALUE;
Fabrice Bellard
committed
s->streams[s->nb_streams++] = st;
return st;
}
Nico Sabbi
committed
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
AVProgram *av_new_program(AVFormatContext *ac, int id)
{
AVProgram *program=NULL;
int i;
#ifdef DEBUG_SI
av_log(ac, AV_LOG_DEBUG, "new_program: id=0x%04x\n", id);
#endif
for(i=0; i<ac->nb_programs; i++)
if(ac->programs[i]->id == id)
program = ac->programs[i];
if(!program){
program = av_mallocz(sizeof(AVProgram));
if (!program)
return NULL;
dynarray_add(&ac->programs, &ac->nb_programs, program);
program->discard = AVDISCARD_NONE;
}
program->id = id;
return program;
}
void av_set_program_name(AVProgram *program, char *provider_name, char *name)
{
assert(!provider_name == !name);
if(name){
av_free(program->provider_name);
av_free(program-> name);
program->provider_name = av_strdup(provider_name);
program-> name = av_strdup( name);
}
}
AVChapter *ff_new_chapter(AVFormatContext *s, int id, AVRational time_base, int64_t start, int64_t end, const char *title)
Michael Niedermayer
committed
AVChapter *chapter = NULL;
int i;
Michael Niedermayer
committed
for(i=0; i<s->nb_chapters; i++)
Michael Niedermayer
committed
if(s->chapters[i]->id == id)
chapter = s->chapters[i];
if(!chapter){
chapter= av_mallocz(sizeof(AVChapter));
Michael Niedermayer
committed
return NULL;
Michael Niedermayer
committed
dynarray_add(&s->chapters, &s->nb_chapters, chapter);
Michael Niedermayer
committed
}
Michael Niedermayer
committed
chapter->id = id;
chapter->time_base= time_base;
Michael Niedermayer
committed
return chapter;
Nico Sabbi
committed
Fabrice Bellard
committed
/************************************************************/
/* output media file */
int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap)
{
int ret;
if (s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (!s->priv_data)
return AVERROR(ENOMEM);
} else
s->priv_data = NULL;
if (s->oformat->set_parameters) {
ret = s->oformat->set_parameters(s, ap);
if (ret < 0)
return ret;
}
return 0;
}
Fabrice Bellard
committed
int av_write_header(AVFormatContext *s)
{
int ret, i;
AVStream *st;
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
// some sanity checks
for(i=0;i<s->nb_streams;i++) {
st = s->streams[i];
switch (st->codec->codec_type) {
case CODEC_TYPE_AUDIO:
if(st->codec->sample_rate<=0){
av_log(s, AV_LOG_ERROR, "sample rate not set\n");
return -1;
}
break;
case CODEC_TYPE_VIDEO:
if(st->codec->time_base.num<=0 || st->codec->time_base.den<=0){ //FIXME audio too?
av_log(s, AV_LOG_ERROR, "time base not set\n");
return -1;
}
if(st->codec->width<=0 || st->codec->height<=0){
av_log(s, AV_LOG_ERROR, "dimensions not set\n");
return -1;
}
break;
}
Michael Niedermayer
committed
if(s->oformat->codec_tag){
if(st->codec->codec_tag){
//FIXME
//check that tag + id is in the table
Michael Niedermayer
committed
//if tag is in the table with another id -> FAIL
//if id is in the table with another tag -> FAIL unless strict < ?
}else
st->codec->codec_tag= av_codec_get_tag(s->oformat->codec_tag, st->codec->codec_id);
}
if (!s->priv_data && s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (!s->priv_data)
return AVERROR(ENOMEM);
if(s->oformat->write_header){
ret = s->oformat->write_header(s);
if (ret < 0)
return ret;
}
/* init PTS generation */
for(i=0;i<s->nb_streams;i++) {
Wolfram Gloger
committed
int64_t den = AV_NOPTS_VALUE;
Michael Niedermayer
committed
switch (st->codec->codec_type) {
Wolfram Gloger
committed
den = (int64_t)st->time_base.num * st->codec->sample_rate;
break;
case CODEC_TYPE_VIDEO:
Wolfram Gloger
committed
den = (int64_t)st->time_base.num * st->codec->time_base.den;
break;
default:
break;
}
Wolfram Gloger
committed
if (den != AV_NOPTS_VALUE) {
if (den <= 0)
return AVERROR_INVALIDDATA;
av_frac_init(&st->pts, 0, 0, den);
}
Fabrice Bellard
committed
}
//FIXME merge with compute_pkt_fields
Michael Niedermayer
committed
static int compute_pkt_fields2(AVStream *st, AVPacket *pkt){
int delay = FFMAX(st->codec->has_b_frames, !!st->codec->max_b_frames);
int num, den, frame_size, i;
// av_log(st->codec, AV_LOG_DEBUG, "av_write_frame: pts:%"PRId64" dts:%"PRId64" cur_dts:%"PRId64" b:%d size:%d st:%d\n", pkt->pts, pkt->dts, st->cur_dts, delay, pkt->size, pkt->stream_index);
/* if(pkt->pts == AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE)
return -1;*/
if (pkt->duration == 0) {
compute_frame_duration(&num, &den, st, NULL, pkt);
if (den && num) {
pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num);
}
}
Michael Niedermayer
committed
if(pkt->pts == AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && delay==0)
pkt->pts= pkt->dts;
//XXX/FIXME this is a temporary hack until all encoders output pts
if((pkt->pts == 0 || pkt->pts == AV_NOPTS_VALUE) && pkt->dts == AV_NOPTS_VALUE && !delay){
pkt->dts=
// pkt->pts= st->cur_dts;
pkt->pts= st->pts.val;
}
if(pkt->pts != AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE){
st->pts_buffer[0]= pkt->pts;
for(i=1; i<delay+1 && st->pts_buffer[i] == AV_NOPTS_VALUE; i++)
st->pts_buffer[i]= (i-delay-1) * pkt->duration;
for(i=0; i<delay && st->pts_buffer[i] > st->pts_buffer[i+1]; i++)
FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i+1]);
pkt->dts= st->pts_buffer[0];
Michael Niedermayer
committed
if(st->cur_dts && st->cur_dts != AV_NOPTS_VALUE && st->cur_dts >= pkt->dts){
av_log(st->codec, AV_LOG_ERROR, "error, non monotone timestamps %"PRId64" >= %"PRId64"\n", st->cur_dts, pkt->dts);
Michael Niedermayer
committed
return -1;
}
if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts < pkt->dts){
av_log(st->codec, AV_LOG_ERROR, "error, pts < dts\n");
Michael Niedermayer
committed
return -1;
}
// av_log(NULL, AV_LOG_DEBUG, "av_write_frame: pts2:%"PRId64" dts2:%"PRId64"\n", pkt->pts, pkt->dts);
st->cur_dts= pkt->dts;
st->pts.val= pkt->dts;
Michael Niedermayer
committed
switch (st->codec->codec_type) {
Michael Niedermayer
committed
frame_size = get_audio_frame_size(st->codec, pkt->size);
/* HACK/FIXME, we skip the initial 0 size packets as they are most
likely equal to the encoder delay, but it would be better if we
had the real timestamps from the encoder */
if (frame_size >= 0 && (pkt->size || st->pts.num!=st->pts.den>>1 || st->pts.val)) {
av_frac_add(&st->pts, (int64_t)st->time_base.den * frame_size);
Fabrice Bellard
committed
}
break;
case CODEC_TYPE_VIDEO:
Michael Niedermayer
committed
av_frac_add(&st->pts, (int64_t)st->time_base.den * st->codec->time_base.num);
break;
default:
break;
}
Michael Niedermayer
committed
return 0;
}
static void truncate_ts(AVStream *st, AVPacket *pkt){
int64_t pts_mask = (2LL << (st->pts_wrap_bits-1)) - 1;
// pkt->dts= 0; //this happens for low_delay=0 and B-frames, FIXME, needs further investigation about what we should do here
if (pkt->pts != AV_NOPTS_VALUE)
Andy Parkins
committed
pkt->pts &= pts_mask;
if (pkt->dts != AV_NOPTS_VALUE)
Andy Parkins
committed
pkt->dts &= pts_mask;
}
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
{
int ret = compute_pkt_fields2(s->streams[pkt->stream_index], pkt);
Michael Niedermayer
committed
if(ret<0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
Michael Niedermayer
committed
return ret;
truncate_ts(s->streams[pkt->stream_index], pkt);
ret= s->oformat->write_packet(s, pkt);
if(!ret)
ret= url_ferror(s->pb);
int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush){
Michael Niedermayer
committed
AVPacketList *pktl, **next_point, *this_pktl;
int stream_count=0;
int streams[MAX_STREAMS];
if(pkt){
AVStream *st= s->streams[ pkt->stream_index];
// assert(pkt->destruct != av_destruct_packet); //FIXME
Michael Niedermayer
committed
this_pktl = av_mallocz(sizeof(AVPacketList));
this_pktl->pkt= *pkt;
pkt->destruct= NULL; // not shared -> must keep original from being freed
else
av_dup_packet(&this_pktl->pkt); //shared -> must dup
Michael Niedermayer
committed
next_point = &s->packet_buffer;
while(*next_point){
AVStream *st2= s->streams[ (*next_point)->pkt.stream_index];
int64_t left= st2->time_base.num * (int64_t)st ->time_base.den;
int64_t right= st ->time_base.num * (int64_t)st2->time_base.den;
if((*next_point)->pkt.dts * left > pkt->dts * right) //FIXME this can overflow
break;
next_point= &(*next_point)->next;
}
this_pktl->next= *next_point;
*next_point= this_pktl;
}
Michael Niedermayer
committed
memset(streams, 0, sizeof(streams));
pktl= s->packet_buffer;
while(pktl){
//av_log(s, AV_LOG_DEBUG, "show st:%d dts:%"PRId64"\n", pktl->pkt.stream_index, pktl->pkt.dts);
Michael Niedermayer
committed
if(streams[ pktl->pkt.stream_index ] == 0)
stream_count++;
streams[ pktl->pkt.stream_index ]++;
pktl= pktl->next;
}
if(stream_count && (s->nb_streams == stream_count || flush)){
Michael Niedermayer
committed
pktl= s->packet_buffer;
*out= pktl->pkt;
s->packet_buffer= pktl->next;
Michael Niedermayer
committed
av_freep(&pktl);
return 1;
}else{
av_init_packet(out);
return 0;
}
}
/**
* Interleaves an AVPacket correctly so it can be muxed.
Michael Niedermayer
committed
* @param out the interleaved packet will be output here
* @param in the input packet
* @param flush 1 if no further packets are available as input and all
* remaining packets should be output
* @return 1 if a packet was output, 0 if no packet could be output,
Michael Niedermayer
committed
*/
static int av_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, int flush){
if(s->oformat->interleave_packet)
return s->oformat->interleave_packet(s, out, in, flush);
else
return av_interleave_packet_per_dts(s, out, in, flush);
}
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){
AVStream *st= s->streams[ pkt->stream_index];
//FIXME/XXX/HACK drop zero sized packets
Michael Niedermayer
committed
if(st->codec->codec_type == CODEC_TYPE_AUDIO && pkt->size==0)
Michael Niedermayer
committed
//av_log(NULL, AV_LOG_DEBUG, "av_interleaved_write_frame %d %"PRId64" %"PRId64"\n", pkt->size, pkt->dts, pkt->pts);
Michael Niedermayer
committed
if(compute_pkt_fields2(st, pkt) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
Michael Niedermayer
committed
return -1;
if(pkt->dts == AV_NOPTS_VALUE)
return -1;
Michael Niedermayer
committed
for(;;){
AVPacket opkt;
int ret= av_interleave_packet(s, &opkt, pkt, 0);
if(ret<=0) //FIXME cleanup needed for ret<0 ?
return ret;
Michael Niedermayer
committed
truncate_ts(s->streams[opkt.stream_index], &opkt);
ret= s->oformat->write_packet(s, &opkt);
Michael Niedermayer
committed
av_free_packet(&opkt);
pkt= NULL;
if(ret<0)
return ret;
if(url_ferror(s->pb))
return url_ferror(s->pb);
Fabrice Bellard
committed
}
int av_write_trailer(AVFormatContext *s)
{
int ret, i;
Michael Niedermayer
committed
for(;;){
AVPacket pkt;
ret= av_interleave_packet(s, &pkt, NULL, 1);
if(ret<0) //FIXME cleanup needed for ret<0 ?
goto fail;
Michael Niedermayer
committed
if(!ret)
break;
Michael Niedermayer
committed
truncate_ts(s->streams[pkt.stream_index], &pkt);
ret= s->oformat->write_packet(s, &pkt);
Michael Niedermayer
committed
av_free_packet(&pkt);
goto fail;
if(url_ferror(s->pb))
if(s->oformat->write_trailer)
ret = s->oformat->write_trailer(s);
ret=url_ferror(s->pb);
for(i=0;i<s->nb_streams;i++)
av_freep(&s->streams[i]->priv_data);
Fabrice Bellard
committed
av_freep(&s->priv_data);
return ret;
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx)
{
int i, j;
AVProgram *program=NULL;
void *tmp;
for(i=0; i<ac->nb_programs; i++){
if(ac->programs[i]->id != progid)
continue;
program = ac->programs[i];
for(j=0; j<program->nb_stream_indexes; j++)
if(program->stream_index[j] == idx)
return;
tmp = av_realloc(program->stream_index, sizeof(unsigned int)*(program->nb_stream_indexes+1));
if(!tmp)
return;
program->stream_index = tmp;
program->stream_index[program->nb_stream_indexes++] = idx;
return;
}
}
Baptiste Coudurier
committed
static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
Nico Sabbi
committed
{
Baptiste Coudurier
committed
char buf[256];
Nico Sabbi
committed
int flags = (is_output ? ic->oformat->flags : ic->iformat->flags);
AVStream *st = ic->streams[i];
int g = ff_gcd(st->time_base.num, st->time_base.den);
avcodec_string(buf, sizeof(buf), st->codec, is_output);
av_log(NULL, AV_LOG_INFO, " Stream #%d.%d", index, i);
/* the pid is an important information, so we display it */
/* XXX: add a generic system */
if (flags & AVFMT_SHOW_IDS)
av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id);
if (strlen(st->language) > 0)
av_log(NULL, AV_LOG_INFO, "(%s)", st->language);
av_log(NULL, AV_LOG_DEBUG, ", %d/%d", st->time_base.num/g, st->time_base.den/g);
av_log(NULL, AV_LOG_INFO, ": %s", buf);
if(st->codec->codec_type == CODEC_TYPE_VIDEO){
if(st->r_frame_rate.den && st->r_frame_rate.num)
av_log(NULL, AV_LOG_INFO, ", %5.2f tb(r)", av_q2d(st->r_frame_rate));
Nico Sabbi
committed
/* else if(st->time_base.den && st->time_base.num)
av_log(NULL, AV_LOG_INFO, ", %5.2f tb(m)", 1/av_q2d(st->time_base));*/
Nico Sabbi
committed
else
av_log(NULL, AV_LOG_INFO, ", %5.2f tb(c)", 1/av_q2d(st->codec->time_base));
Nico Sabbi
committed
}
av_log(NULL, AV_LOG_INFO, "\n");
}
av_log(NULL, AV_LOG_INFO, "%s #%d, %s, %s '%s':\n",
index,
is_output ? ic->oformat->name : ic->iformat->name,
Fabrice Bellard
committed
if (!is_output) {
av_log(NULL, AV_LOG_INFO, " Duration: ");
Fabrice Bellard
committed
if (ic->duration != AV_NOPTS_VALUE) {
int hours, mins, secs, us;
secs = ic->duration / AV_TIME_BASE;
us = ic->duration % AV_TIME_BASE;
mins = secs / 60;
secs %= 60;
hours = mins / 60;
mins %= 60;
av_log(NULL, AV_LOG_INFO, "%02d:%02d:%02d.%02d", hours, mins, secs,
(100 * us) / AV_TIME_BASE);
Fabrice Bellard
committed
} else {
av_log(NULL, AV_LOG_INFO, "N/A");
Fabrice Bellard
committed
}
Wolfram Gloger
committed
if (ic->start_time != AV_NOPTS_VALUE) {
int secs, us;
av_log(NULL, AV_LOG_INFO, ", start: ");
Wolfram Gloger
committed
secs = ic->start_time / AV_TIME_BASE;
us = ic->start_time % AV_TIME_BASE;
av_log(NULL, AV_LOG_INFO, "%d.%06d",
Wolfram Gloger
committed
secs, (int)av_rescale(us, 1000000, AV_TIME_BASE));
}
av_log(NULL, AV_LOG_INFO, ", bitrate: ");
Fabrice Bellard
committed
if (ic->bit_rate) {
av_log(NULL, AV_LOG_INFO,"%d kb/s", ic->bit_rate / 1000);
Fabrice Bellard
committed
} else {
av_log(NULL, AV_LOG_INFO, "N/A");
Fabrice Bellard
committed
}
av_log(NULL, AV_LOG_INFO, "\n");
Fabrice Bellard
committed
}
if(ic->nb_programs) {
int j, k;
for(j=0; j<ic->nb_programs; j++) {
av_log(NULL, AV_LOG_INFO, " Program %d %s\n", ic->programs[j]->id,
ic->programs[j]->name ? ic->programs[j]->name : "");
for(k=0; k<ic->programs[j]->nb_stream_indexes; k++)
Baptiste Coudurier
committed
dump_stream_format(ic, ic->programs[j]->stream_index[k], index, is_output);
}
} else
Nico Sabbi
committed
for(i=0;i<ic->nb_streams;i++)
Baptiste Coudurier
committed
dump_stream_format(ic, i, index, is_output);
}
int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
{
Stefano Sabatini
committed
return av_parse_video_frame_size(width_ptr, height_ptr, str);
Stefano Sabatini
committed
int parse_frame_rate(int *frame_rate_num, int *frame_rate_den, const char *arg)
Stefano Sabatini
committed
AVRational frame_rate;
int ret = av_parse_video_frame_rate(&frame_rate, arg);
*frame_rate_num= frame_rate.num;
*frame_rate_den= frame_rate.den;
return ret;
*/
int64_t av_gettime(void)
{
struct timeval tv;
gettimeofday(&tv,NULL);
return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
}
int64_t parse_date(const char *datestr, int duration)
Philip Gladstone
committed
struct tm dt;
Philip Gladstone
committed
int i;
static const char *date_fmt[] = {
"%Y-%m-%d",
"%Y%m%d",
};
static const char *time_fmt[] = {
"%H:%M:%S",
"%H%M%S",
};
const char *q;
Philip Gladstone
committed
char lastch;
#undef time
Philip Gladstone
committed
time_t now = time(0);
len = strlen(datestr);
if (len > 0)
lastch = datestr[len - 1];
else
lastch = '\0';
Philip Gladstone
committed
is_utc = (lastch == 'z' || lastch == 'Z');
Philip Gladstone
committed
memset(&dt, 0, sizeof(dt));
/* parse the year-month-day part */
Philip Gladstone
committed
for (i = 0; i < sizeof(date_fmt) / sizeof(date_fmt[0]); i++) {
Fabrice Bellard
committed
q = small_strptime(p, date_fmt[i], &dt);
Philip Gladstone
committed
if (q) {
break;
}
}
/* if the year-month-day part is missing, then take the
* current year-month-day time */
Philip Gladstone
committed
if (!q) {
if (is_utc) {
dt = *gmtime(&now);
} else {
dt = *localtime(&now);
}
dt.tm_hour = dt.tm_min = dt.tm_sec = 0;
Philip Gladstone
committed
p = q;
Philip Gladstone
committed
if (*p == 'T' || *p == 't' || *p == ' ')
p++;
/* parse the hour-minute-second part */
for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) {
Fabrice Bellard
committed
q = small_strptime(p, time_fmt[i], &dt);
if (q) {
break;
}
}
} else {
/* parse datestr as a duration */
if (p[0] == '-') {
negative = 1;
++p;
}
/* parse datestr as HH:MM:SS */
Fabrice Bellard
committed
q = small_strptime(p, time_fmt[0], &dt);
/* parse datestr as S+ */
if (q == p)
/* the parsing didn't succeed */
return INT64_MIN;
Philip Gladstone
committed
}
}
/* Now we have all the fields that we can get */
if (!q) {
return INT64_MIN;
Philip Gladstone
committed
if (duration) {
Philip Gladstone
committed
t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
Philip Gladstone
committed
} else {
Philip Gladstone
committed
dt.tm_isdst = -1; /* unknown */
if (is_utc) {
t = mktimegm(&dt);
} else {
t = mktime(&dt);
}
Philip Gladstone
committed
Philip Gladstone
committed
t *= 1000000;
/* parse the .m... part */
Philip Gladstone
committed
if (*q == '.') {
Philip Gladstone
committed
q++;
for (val = 0, n = 100000; n >= 1; n /= 10, q++) {
Philip Gladstone
committed
break;
val += n * (*q - '0');
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
}
int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
{
const char *p;
char tag[128], *q;
p = info;
if (*p == '?')
p++;
for(;;) {
q = tag;
while (*p != '\0' && *p != '=' && *p != '&') {
if ((q - tag) < sizeof(tag) - 1)
*q++ = *p;
p++;
}
*q = '\0';
q = arg;
if (*p == '=') {
p++;
while (*p != '&' && *p != '\0') {
Philip Gladstone
committed
if ((q - arg) < arg_size - 1) {
if (*p == '+')
*q++ = ' ';
else
*q++ = *p;
}
Michel Bardiaux
committed
int av_get_frame_filename(char *buf, int buf_size,
const char *path, int number)
Panagiotis Issaris
committed
char *q, buf1[20], c;
int nd, len, percentd_found;
q = buf;
p = path;
percentd_found = 0;
for(;;) {
c = *p++;
if (c == '\0')
break;
if (c == '%') {
Philip Gladstone
committed
do {
nd = 0;
while (isdigit(*p)) {
nd = nd * 10 + *p++ - '0';
}
c = *p++;
} while (isdigit(c));
switch(c) {
case '%':
goto addchar;
case 'd':
if (percentd_found)
goto fail;
percentd_found = 1;
snprintf(buf1, sizeof(buf1), "%0*d", nd, number);
len = strlen(buf1);
if ((q - buf + len) > buf_size - 1)
goto fail;
memcpy(q, buf1, len);
q += len;
break;
default:
goto fail;