Logo Search packages:      
Sourcecode: blender version File versions  Download package

int av_find_stream_info ( AVFormatContext *  ic  ) 

Read the beginning of a media file to get stream information. This is useful for file formats with no headers such as MPEG. This function also compute the real frame rate in case of mpeg2 repeat frame mode.

Parameters:
ic media file handle
Returns:
>=0 if OK. AVERROR_xxx if error.
Todo:
let user decide somehow what information is needed so we dont waste time geting stuff the user doesnt need

Definition at line 1861 of file utils.c.

References av_malloc(), av_q2d(), av_reduce(), av_rescale(), and av_rescale_q().

{
    int i, count, ret, read_size, j;
    AVStream *st;
    AVPacket pkt1, *pkt;
    AVPacketList *pktl=NULL, **ppktl;
    int64_t last_dts[MAX_STREAMS];
    int64_t duration_sum[MAX_STREAMS];
    int duration_count[MAX_STREAMS]={0};

    for(i=0;i<ic->nb_streams;i++) {
        st = ic->streams[i];
        if(st->codec->codec_type == CODEC_TYPE_VIDEO){
/*            if(!st->time_base.num)
                st->time_base= */
            if(!st->codec->time_base.num)
                st->codec->time_base= st->time_base;
        }
        //only for the split stuff
        if (!st->parser) {
            st->parser = av_parser_init(st->codec->codec_id);
            if(st->need_parsing == 2 && st->parser){
                st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
            }
        }
    }

    for(i=0;i<MAX_STREAMS;i++){
        last_dts[i]= AV_NOPTS_VALUE;
        duration_sum[i]= INT64_MAX;
    }

    count = 0;
    read_size = 0;
    ppktl = &ic->packet_buffer;
    for(;;) {
        /* check if one codec still needs to be handled */
        for(i=0;i<ic->nb_streams;i++) {
            st = ic->streams[i];
            if (!has_codec_parameters(st->codec))
                break;
            /* variable fps and no guess at the real fps */
            if(   st->codec->time_base.den >= 101LL*st->codec->time_base.num
               && duration_count[i]<20 && st->codec->codec_type == CODEC_TYPE_VIDEO)
                break;
            if(st->parser && st->parser->parser->split && !st->codec->extradata)
                break;
        }
        if (i == ic->nb_streams) {
            /* NOTE: if the format has no header, then we need to read
               some packets to get most of the streams, so we cannot
               stop here */
            if (!(ic->ctx_flags & AVFMTCTX_NOHEADER)) {
                /* if we found the info for all the codecs, we can stop */
                ret = count;
                break;
            }
        } else {
            /* we did not get all the codec info, but we read too much data */
            if (read_size >= MAX_READ_SIZE) {
                ret = count;
                break;
            }
        }

        /* NOTE: a new stream can be added there if no header in file
           (AVFMTCTX_NOHEADER) */
        ret = av_read_frame_internal(ic, &pkt1);
        if (ret < 0) {
            /* EOF or error */
            ret = -1; /* we could not have all the codec parameters before EOF */
            for(i=0;i<ic->nb_streams;i++) {
                st = ic->streams[i];
                if (!has_codec_parameters(st->codec)){
                    char buf[256];
                    avcodec_string(buf, sizeof(buf), st->codec, 0);
                    av_log(ic, AV_LOG_INFO, "Could not find codec parameters (%s)\n", buf);
                    break;
                }
            }
            if (i == ic->nb_streams)
                ret = 0;
            break;
        }

        pktl = av_mallocz(sizeof(AVPacketList));
        if (!pktl) {
            ret = AVERROR_NOMEM;
            break;
        }

        /* add the packet in the buffered packet list */
        *ppktl = pktl;
        ppktl = &pktl->next;

        pkt = &pktl->pkt;
        *pkt = pkt1;

        /* duplicate the packet */
        if (av_dup_packet(pkt) < 0) {
                ret = AVERROR_NOMEM;
                break;
        }

        read_size += pkt->size;

        st = ic->streams[pkt->stream_index];
        st->codec_info_duration += pkt->duration;
        if (pkt->duration != 0)
            st->codec_info_nb_frames++;

        {
            int index= pkt->stream_index;
            int64_t last= last_dts[index];
            int64_t duration= pkt->dts - last;

            if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && duration>0){
                if(duration*duration_count[index]*10/9 < duration_sum[index]){
                    duration_sum[index]= duration;
                    duration_count[index]=1;
                }else{
                    int factor= av_rescale(duration, duration_count[index], duration_sum[index]);
                    duration_sum[index] += duration;
                    duration_count[index]+= factor;
                }
                if(st->codec_info_nb_frames == 0 && 0)
                    st->codec_info_duration += duration;
            }
            last_dts[pkt->stream_index]= pkt->dts;
        }
        if(st->parser && st->parser->parser->split && !st->codec->extradata){
            int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);
            if(i){
                st->codec->extradata_size= i;
                st->codec->extradata= av_malloc(st->codec->extradata_size);
                memcpy(st->codec->extradata, pkt->data, st->codec->extradata_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 MPEG4, 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 (av_rescale_q(st->codec_info_duration, st->time_base, AV_TIME_BASE_Q) >= MAX_STREAM_DURATION) {
            break;
        }
        count++;
    }

    // close codecs which where 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);
    }
    for(i=0;i<ic->nb_streams;i++) {
        st = ic->streams[i];
        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] && st->codec->time_base.num*101LL <= st->codec->time_base.den &&
               st->time_base.num*duration_sum[i]/duration_count[i]*101LL > st->time_base.den){
                int64_t num, den, error, best_error;

                num= st->time_base.den*duration_count[i];
                den= st->time_base.num*duration_sum[i];

                best_error= INT64_MAX;
                for(j=1; j<60*12; j++){
                    error= ABS(1001*12*num - 1001*j*den);
                    if(error < best_error){
                        best_error= error;
                        av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, j, 12, INT_MAX);
                    }
                }
                for(j=24; j<=30; j+=6){
                    error= ABS(1001*12*num - 1000*12*j*den);
                    if(error < best_error){
                        best_error= error;
                        av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, j*1000, 1001, INT_MAX);
                    }
                }
            }

            /* set real frame rate info */
            /* compute the real frame rate for telecine */
            if ((st->codec->codec_id == CODEC_ID_MPEG1VIDEO ||
                 st->codec->codec_id == CODEC_ID_MPEG2VIDEO) &&
                st->codec->sub_id == 2) {
                if (st->codec_info_nb_frames >= 20) {
                    float coded_frame_rate, est_frame_rate;
                    est_frame_rate = ((double)st->codec_info_nb_frames * AV_TIME_BASE) /
                        (double)st->codec_info_duration ;
                    coded_frame_rate = 1.0/av_q2d(st->codec->time_base);
#if 0
                    printf("telecine: coded_frame_rate=%0.3f est_frame_rate=%0.3f\n",
                           coded_frame_rate, est_frame_rate);
#endif
                    /* if we detect that it could be a telecine, we
                       signal it. It would be better to do it at a
                       higher level as it can change in a film */
                    if (coded_frame_rate >= 24.97 &&
                        (est_frame_rate >= 23.5 && est_frame_rate < 24.5)) {
                        st->r_frame_rate = (AVRational){24000, 1001};
                    }
                }
            }
            /* if no real frame rate, use the codec one */
            if (!st->r_frame_rate.num){
                st->r_frame_rate.num = st->codec->time_base.den;
                st->r_frame_rate.den = st->codec->time_base.num;
            }
        }
    }

    av_estimate_timings(ic);
#if 0
    /* 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
    return ret;
}


Generated by  Doxygen 1.6.0   Back to index