⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utils.c

📁 ffmpeg源码分析
💻 C
📖 第 1 页 / 共 5 页
字号:
    url_fseek(&ic->pb, 0, SEEK_SET);}static void av_estimate_timings(AVFormatContext *ic){    int64_t file_size;    /* get the file size, if possible */    if (ic->iformat->flags & AVFMT_NOFILE) {        file_size = 0;    } else {        file_size = url_fsize(&ic->pb);        if (file_size < 0)            file_size = 0;    }    ic->file_size = file_size;    if ((ic->iformat == &mpegps_demux || ic->iformat == &mpegts_demux) && file_size && !ic->pb.is_streamed) {        /* get accurate estimate from the PTSes */        av_estimate_timings_from_pts(ic);    } else if (av_has_timings(ic)) {        /* at least one components has timings - we use them for all           the components */        fill_all_stream_timings(ic);    } else {        /* less precise: use bit rate info */        av_estimate_timings_from_bit_rate(ic);    }    av_update_stream_timings(ic);#if 0    {        int i;        AVStream *st;        for(i = 0;i < ic->nb_streams; i++) {            st = ic->streams[i];        printf("%d: start_time: %0.3f duration: %0.3f\n",               i, (double)st->start_time / AV_TIME_BASE,               (double)st->duration / AV_TIME_BASE);        }        printf("stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n",               (double)ic->start_time / AV_TIME_BASE,               (double)ic->duration / AV_TIME_BASE,               ic->bit_rate / 1000);    }#endif}static int has_codec_parameters(AVCodecContext *enc){    int val;    switch(enc->codec_type) {    case CODEC_TYPE_AUDIO:        val = enc->sample_rate;        break;    case CODEC_TYPE_VIDEO:        val = enc->width && enc->pix_fmt != PIX_FMT_NONE;        break;    default:        val = 1;        break;    }    return (val != 0);}static int try_decode_frame(AVStream *st, const uint8_t *data, int size){    int16_t *samples;    AVCodec *codec;    int got_picture, ret=0;    AVFrame picture;  if(!st->codec->codec){    codec = avcodec_find_decoder(st->codec->codec_id);    if (!codec)        return -1;    ret = avcodec_open(st->codec, codec);    if (ret < 0)        return ret;  }  if(!has_codec_parameters(st->codec)){    switch(st->codec->codec_type) {    case CODEC_TYPE_VIDEO:        ret = avcodec_decode_video(st->codec, &picture,                                   &got_picture, (uint8_t *)data, size);        break;    case CODEC_TYPE_AUDIO:        samples = av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);        if (!samples)            goto fail;        ret = avcodec_decode_audio(st->codec, samples,                                   &got_picture, (uint8_t *)data, size);        av_free(samples);        break;    default:        break;    }  } fail:    return ret;}/* absolute maximum size we read until we abort */#define MAX_READ_SIZE        5000000/* maximum duration until we stop analysing the stream */#define MAX_STREAM_DURATION  ((int)(AV_TIME_BASE * 2.0))/** * 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. * * @param ic media file handle * @return >=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 */int av_find_stream_info(AVFormatContext *ic){    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;}/*******************************************************//** * start playing a network based stream (e.g. RTSP stream) at the * current position */int av_read_play(AVFormatContext *s){    if (!s->iformat->read_play)        return AVERROR_NOTSUPP;    return s->iformat->read_play(s);}/** * Pause a network based stream (e.g. RTSP stream). * * Use av_read_play() to resume it. */int av_read_pause(AVFormatContext *s){    if (!s->iformat->read_pause)        return AVERROR_NOTSUPP;    return s->iformat->read_pause(s);}/** * Close a media file (but not its codecs). * * @param s media file handle */void av_close_input_file(AVFormatContext *s){    int i, must_open_file;    AVStream *st;    /* free previous packet */    if (s->cur_st && s->cur_st->parser)        av_free_packet(&s->cur_pkt);    if (s->iformat->read_close)        s->iformat->read_close(s);    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);        }        av_free(st->index_entries);        av_free(st->codec);        av_free(st);    }    flush_pack

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -