Skip to content
Snippets Groups Projects
utils.c 97.5 KiB
Newer Older
  • Learn to ignore specific revisions
  •             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)
    
                        memset(duration_error[index], 0, sizeof(*duration_error));
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                    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;
    
    John Donaghy's avatar
    John Donaghy committed
    
                if (st->codec->codec_id == CODEC_ID_NONE) {
                    AVProbeData *pd = &(probe_data[st->index]);
    
                    pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE);
    
    John Donaghy's avatar
    John Donaghy committed
                    memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size);
                    pd->buf_size += pkt->size;
    
                    memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE);
    
            if(st->parser && st->parser->parser->split && !st->codec->extradata){
                int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);
    
                    st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
    
                    memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size);
    
                    memset(st->codec->extradata + i, 0, FF_INPUT_BUFFER_PADDING_SIZE);
    
            /* 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. */
    
            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) {
    
    Diego Biurrun's avatar
    Diego Biurrun committed
        // close codecs which were opened in try_decode_frame()
    
        for(i=0;i<ic->nb_streams;i++) {
            st = ic->streams[i];
    
            if(st->codec->codec)
                avcodec_close(st->codec);
    
            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);
    
                   && 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->r_frame_rate.num){
    
                    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;
                    }
    
            }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);
    
    John Donaghy's avatar
    John Donaghy committed
                    if (codec_identified[st->index]) {
    
                        st->need_parsing = AVSTREAM_PARSE_FULL;
    
                if(!st->codec->bits_per_sample)
                    st->codec->bits_per_sample= av_get_bits_per_sample(st->codec->codec_id);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
        av_estimate_timings(ic, old_offset);
    
    John Donaghy's avatar
    John Donaghy committed
    
        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);
    
        /* correct DTS for B-frame streams with no timestamps */
    
        for(i=0;i<ic->nb_streams;i++) {
            st = ic->streams[i];
    
            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
    
    John Donaghy's avatar
    John Donaghy committed
        for(i=0;i<MAX_STREAMS;i++){
            av_freep(&(probe_data[i].buf));
        }
    
    /*******************************************************/
    
    int av_read_play(AVFormatContext *s)
    {
    
        if (s->iformat->read_play)
            return s->iformat->read_play(s);
    
            return av_url_read_fpause(s->pb, 0);
    
    }
    
    int av_read_pause(AVFormatContext *s)
    {
    
        if (s->iformat->read_pause)
            return s->iformat->read_pause(s);
    
            return av_url_read_fpause(s->pb, 1);
    
    void av_close_input_stream(AVFormatContext *s)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        /* free previous packet */
        if (s->cur_st && s->cur_st->parser)
    
            av_free_packet(&s->cur_pkt);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        for(i=0;i<s->nb_streams;i++) {
    
            /* free all data in a stream component */
            st = s->streams[i];
    
            if (st->parser) {
                av_parser_close(st->parser);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
    
            av_free(st->index_entries);
    
            av_free(st->codec->extradata);
    
            av_free(st->filename);
    
    Fabrice Bellard's avatar
    Fabrice Bellard 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);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        av_freep(&s->programs);
    
        while(s->nb_chapters--) {
            av_free(s->chapters[s->nb_chapters]->title);
            av_free(s->chapters[s->nb_chapters]);
    
        }
        av_freep(&s->chapters);
    
        av_free(s);
    
    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);
    }
    
    
    AVStream *av_new_stream(AVFormatContext *s, int id)
    {
        AVStream *st;
    
    
        if (s->nb_streams >= MAX_STREAMS)
            return NULL;
    
        st = av_mallocz(sizeof(AVStream));
        if (!st)
            return NULL;
    
        if (s->iformat) {
            /* no default bitrate if decoding */
    
        st->start_time = AV_NOPTS_VALUE;
        st->duration = AV_NOPTS_VALUE;
    
            /* 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;
    
        /* default pts setting is MPEG-like */
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        st->last_IP_pts = AV_NOPTS_VALUE;
    
        for(i=0; i<MAX_REORDER_DELAY+1; i++)
            st->pts_buffer[i]= AV_NOPTS_VALUE;
    
    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)
    
            if(s->chapters[i]->id == id)
                chapter = s->chapters[i];
    
        if(!chapter){
            chapter= av_mallocz(sizeof(AVChapter));
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            if(!chapter)
    
            dynarray_add(&s->chapters, &s->nb_chapters, chapter);
    
    Aurelien Jacobs's avatar
    Aurelien Jacobs committed
        av_free(chapter->title);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        chapter->title = av_strdup(title);
    
        chapter->time_base= time_base;
    
        chapter->start = start;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        chapter->end   = end;
    
    /************************************************************/
    /* output media file */
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
    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)
    
        } else
            s->priv_data = NULL;
    
        if (s->oformat->set_parameters) {
            ret = s->oformat->set_parameters(s, ap);
            if (ret < 0)
                return ret;
        }
        return 0;
    }
    
    
        // 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;
            }
    
    
            if(s->oformat->codec_tag){
                if(st->codec->codec_tag){
                    //FIXME
                    //check that tag + id is in the table
    
                    //if neither is in the table -> OK
    
                    //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)
    
        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++) {
    
            case CODEC_TYPE_AUDIO:
    
                den = (int64_t)st->time_base.num * st->codec->sample_rate;
    
                break;
            case CODEC_TYPE_VIDEO:
    
                den = (int64_t)st->time_base.num * st->codec->time_base.den;
    
            if (den != AV_NOPTS_VALUE) {
                if (den <= 0)
                    return AVERROR_INVALIDDATA;
                av_frac_init(&st->pts, 0, 0, den);
            }
    
    //FIXME merge with compute_pkt_fields
    
    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;*/
    
        /* duration field */
    
        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);
            }
        }
    
        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;
        }
    
    
        //calculate dts from pts
    
        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]);
    
        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);
    
            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");
    
    //    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;
    
    
        case CODEC_TYPE_AUDIO:
    
            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);
    
            break;
        case CODEC_TYPE_VIDEO:
    
            av_frac_add(&st->pts, (int64_t)st->time_base.den * st->codec->time_base.num);
    
    }
    
    static void truncate_ts(AVStream *st, AVPacket *pkt){
        int64_t pts_mask = (2LL << (st->pts_wrap_bits-1)) - 1;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    //    if(pkt->dts < 0)
    
    //        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)
    
        if (pkt->dts != AV_NOPTS_VALUE)
    
    }
    
    int av_write_frame(AVFormatContext *s, AVPacket *pkt)
    {
    
        int ret = compute_pkt_fields2(s->streams[pkt->stream_index], pkt);
    
        if(ret<0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
    
        truncate_ts(s->streams[pkt->stream_index], pkt);
    
    
        ret= s->oformat->write_packet(s, pkt);
        if(!ret)
    
        return ret;
    
    int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush){
    
        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
    
    
            this_pktl = av_mallocz(sizeof(AVPacketList));
            this_pktl->pkt= *pkt;
    
            if(pkt->destruct == av_destruct_packet)
    
                pkt->destruct= NULL; // not shared -> must keep original from being freed
    
            else
                av_dup_packet(&this_pktl->pkt);  //shared -> must dup
    
    
            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;
        }
    
        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);
    
            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)){
    
    
            s->packet_buffer= pktl->next;
    
     * Interleaves an AVPacket correctly so it can be muxed.
    
     * @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,
    
     *         < 0 if an error occurred
    
     */
    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
    
        if(st->codec->codec_type == CODEC_TYPE_AUDIO && pkt->size==0)
    
    //av_log(NULL, AV_LOG_DEBUG, "av_interleaved_write_frame %d %"PRId64" %"PRId64"\n", pkt->size, pkt->dts, pkt->pts);
    
        if(compute_pkt_fields2(st, pkt) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
    
        if(pkt->dts == AV_NOPTS_VALUE)
            return -1;
    
    
        for(;;){
            AVPacket opkt;
            int ret= av_interleave_packet(s, &opkt, pkt, 0);
            if(ret<=0) //FIXME cleanup needed for ret<0 ?
                return ret;
    
            truncate_ts(s->streams[opkt.stream_index], &opkt);
            ret= s->oformat->write_packet(s, &opkt);
    
            if(url_ferror(s->pb))
                return url_ferror(s->pb);
    
        for(;;){
            AVPacket pkt;
            ret= av_interleave_packet(s, &pkt, NULL, 1);
            if(ret<0) //FIXME cleanup needed for ret<0 ?
    
            truncate_ts(s->streams[pkt.stream_index], &pkt);
            ret= s->oformat->write_packet(s, &pkt);
    
                goto fail;
    
        if(s->oformat->write_trailer)
            ret = s->oformat->write_trailer(s);
    
        if(ret == 0)
    
        for(i=0;i<s->nb_streams;i++)
            av_freep(&s->streams[i]->priv_data);
    
    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;
        }
    }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    /* "user interface" functions */
    
    static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
    
        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));
    
    /*      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));*/
    
                av_log(NULL, AV_LOG_INFO, ", %5.2f tb(c)", 1/av_q2d(st->codec->time_base));
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    void dump_format(AVFormatContext *ic,
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                     const char *url,
                     int is_output)
    {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        av_log(NULL, AV_LOG_INFO, "%s #%d, %s, %s '%s':\n",
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                is_output ? "Output" : "Input",
    
                index,
                is_output ? ic->oformat->name : ic->iformat->name,
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                is_output ? "to" : "from", url);
    
            av_log(NULL, AV_LOG_INFO, "  Duration: ");
    
            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);
    
                av_log(NULL, AV_LOG_INFO, "N/A");
    
            if (ic->start_time != AV_NOPTS_VALUE) {
                int secs, us;
    
                av_log(NULL, AV_LOG_INFO, ", start: ");
    
                secs = ic->start_time / AV_TIME_BASE;
                us = ic->start_time % AV_TIME_BASE;
    
                av_log(NULL, AV_LOG_INFO, "%d.%06d",
    
            av_log(NULL, AV_LOG_INFO, ", bitrate: ");
    
                av_log(NULL, AV_LOG_INFO,"%d kb/s", ic->bit_rate / 1000);
    
                av_log(NULL, AV_LOG_INFO, "N/A");
    
            av_log(NULL, AV_LOG_INFO, "\n");
    
        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++)
    
                    dump_stream_format(ic, ic->programs[j]->stream_index[k], index, is_output);
    
            dump_stream_format(ic, i, index, is_output);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
    {
    
        return av_parse_video_frame_size(width_ptr, height_ptr, str);
    
    int parse_frame_rate(int *frame_rate_num, int *frame_rate_den, const char *arg)
    
        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;
    
     * Gets the current time in microseconds.
    
     */
    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)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        const char *p;
    
        int64_t t;
    
        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;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        int is_utc, len;
    
        int negative = 0;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        len = strlen(datestr);
        if (len > 0)
            lastch = datestr[len - 1];
        else
            lastch = '\0';
    
        is_utc = (lastch == 'z' || lastch == 'Z');
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
        p = datestr;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        q = NULL;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        if (!duration) {
    
            /* parse the year-month-day part */
    
            for (i = 0; i < sizeof(date_fmt) / sizeof(date_fmt[0]); i++) {
    
                q = small_strptime(p, date_fmt[i], &dt);
    
            /* if the year-month-day part is missing, then take the
             * current year-month-day time */
    
            if (!q) {
                if (is_utc) {
                    dt = *gmtime(&now);
                } else {
                    dt = *localtime(&now);
                }
                dt.tm_hour = dt.tm_min = dt.tm_sec = 0;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            } else {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
    
            /* parse the hour-minute-second part */
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) {
    
                q = small_strptime(p, time_fmt[i], &dt);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                if (q) {
                    break;
                }
            }
        } else {
    
            /* parse datestr as a duration */
    
            if (p[0] == '-') {
                negative = 1;
                ++p;
            }
    
            /* parse datestr as HH:MM:SS */
    
            q = small_strptime(p, time_fmt[0], &dt);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            if (!q) {
    
                /* parse datestr as S+ */
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                dt.tm_sec = strtol(p, (char **)&q, 10);
    
                if (q == p)
                    /* the parsing didn't succeed */
                    return INT64_MIN;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                dt.tm_min = 0;
                dt.tm_hour = 0;
    
            }
        }
    
        /* Now we have all the fields that we can get */
        if (!q) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
            t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
    
            dt.tm_isdst = -1;       /* unknown */
            if (is_utc) {
                t = mktimegm(&dt);
            } else {
                t = mktime(&dt);
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
        /* parse the .m... part */
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            int val, n;
    
            q++;
            for (val = 0, n = 100000; n >= 1; n /= 10, q++) {
    
                if (!isdigit(*q))
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
            t += val;
        }
    
        return negative ? -t : t;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    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') {
    
                    if ((q - arg) < arg_size - 1) {
                        if (*p == '+')
                            *q++ = ' ';
                        else
                            *q++ = *p;
                    }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    p++;
                }
                *q = '\0';
            }
    
            if (!strcmp(tag, tag1))
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                return 1;
            if (*p != '&')
                break;
    
    int av_get_frame_filename(char *buf, int buf_size,
                              const char *path, int number)
    
    {
        const char *p;
    
    
        q = buf;
        p = path;
        percentd_found = 0;
        for(;;) {
            c = *p++;
            if (c == '\0')
                break;
            if (c == '%') {
    
                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;