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

📄 utils.c

📁 ffmpeg源码分析
💻 C
📖 第 1 页 / 共 5 页
字号:
/** * Open a media file from an IO stream. 'fmt' must be specified. */static const char* format_to_name(void* ptr){    AVFormatContext* fc = (AVFormatContext*) ptr;    if(fc->iformat) return fc->iformat->name;    else if(fc->oformat) return fc->oformat->name;    else return "NULL";}static const AVClass av_format_context_class = { "AVFormatContext", format_to_name };AVFormatContext *av_alloc_format_context(void){    AVFormatContext *ic;    ic = av_mallocz(sizeof(AVFormatContext));    if (!ic) return ic;    ic->av_class = &av_format_context_class;    return ic;}/** * Allocates all the structures needed to read an input stream. *        This does not open the needed codecs for decoding the stream[s]. */int av_open_input_stream(AVFormatContext **ic_ptr,                         ByteIOContext *pb, const char *filename,                         AVInputFormat *fmt, AVFormatParameters *ap){    int err;    AVFormatContext *ic;    AVFormatParameters default_ap;    if(!ap){        ap=&default_ap;        memset(ap, 0, sizeof(default_ap));    }    ic = av_alloc_format_context();    if (!ic) {        err = AVERROR_NOMEM;        goto fail;    }    ic->iformat = fmt;    if (pb)        ic->pb = *pb;    ic->duration = AV_NOPTS_VALUE;    ic->start_time = AV_NOPTS_VALUE;    pstrcpy(ic->filename, sizeof(ic->filename), filename);    /* allocate private data */    if (fmt->priv_data_size > 0) {        ic->priv_data = av_mallocz(fmt->priv_data_size);        if (!ic->priv_data) {            err = AVERROR_NOMEM;            goto fail;        }    } else {        ic->priv_data = NULL;    }    err = ic->iformat->read_header(ic, ap);    if (err < 0)        goto fail;    if (pb)        ic->data_offset = url_ftell(&ic->pb);    *ic_ptr = ic;    return 0; fail:    if (ic) {        av_freep(&ic->priv_data);    }    av_free(ic);    *ic_ptr = NULL;    return err;}/** Size of probe buffer, for guessing file type from file contents. */#define PROBE_BUF_MIN 2048#define PROBE_BUF_MAX 131072/** * Open a media file as input. The codec are not opened. Only the file * header (if present) is read. * * @param ic_ptr the opened media file handle is put here * @param filename filename to open. * @param fmt if non NULL, force the file format to use * @param buf_size optional buffer size (zero if default is OK) * @param ap additionnal parameters needed when opening the file (NULL if default) * @return 0 if OK. AVERROR_xxx otherwise. */int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,                       AVInputFormat *fmt,                       int buf_size,                       AVFormatParameters *ap){    int err, must_open_file, file_opened, probe_size;    AVProbeData probe_data, *pd = &probe_data;    ByteIOContext pb1, *pb = &pb1;    file_opened = 0;    pd->filename = "";    if (filename)        pd->filename = filename;    pd->buf = NULL;    pd->buf_size = 0;    if (!fmt) {        /* guess format if no file can be opened  */        fmt = av_probe_input_format(pd, 0);    }    /* do not open file if the format does not need it. XXX: specific       hack needed to handle RTSP/TCP */    must_open_file = 1;    if (fmt && (fmt->flags & AVFMT_NOFILE)) {        must_open_file = 0;        pb= NULL; //FIXME this or memset(pb, 0, sizeof(ByteIOContext)); otherwise its uninitalized    }    if (!fmt || must_open_file) {        /* if no file needed do not try to open one */        if (url_fopen(pb, filename, URL_RDONLY) < 0) {            err = AVERROR_IO;            goto fail;        }        file_opened = 1;        if (buf_size > 0) {            url_setbufsize(pb, buf_size);        }        for(probe_size= PROBE_BUF_MIN; probe_size<=PROBE_BUF_MAX && !fmt; probe_size<<=1){            /* read probe data */            pd->buf= av_realloc(pd->buf, probe_size);            pd->buf_size = get_buffer(pb, pd->buf, probe_size);            if (url_fseek(pb, 0, SEEK_SET) == (offset_t)-EPIPE) {                url_fclose(pb);                if (url_fopen(pb, filename, URL_RDONLY) < 0) {                    file_opened = 0;                    err = AVERROR_IO;                    goto fail;                }            }            /* guess file format */            fmt = av_probe_input_format(pd, 1);        }        av_freep(&pd->buf);    }    /* if still no format found, error */    if (!fmt) {        err = AVERROR_NOFMT;        goto fail;    }    /* XXX: suppress this hack for redirectors */#ifdef CONFIG_NETWORK    if (fmt == &redir_demux) {        err = redir_open(ic_ptr, pb);        url_fclose(pb);        return err;    }#endif    /* check filename in case of an image number is expected */    if (fmt->flags & AVFMT_NEEDNUMBER) {        if (filename_number_test(filename) < 0) {            err = AVERROR_NUMEXPECTED;            goto fail;        }    }    err = av_open_input_stream(ic_ptr, pb, filename, fmt, ap);    if (err)        goto fail;    return 0; fail:    av_freep(&pd->buf);    if (file_opened)        url_fclose(pb);    *ic_ptr = NULL;    return err;}/*******************************************************//** * Read a transport packet from a media file. * * This function is absolete and should never be used. * Use av_read_frame() instead. * * @param s media file handle * @param pkt is filled * @return 0 if OK. AVERROR_xxx if error. */int av_read_packet(AVFormatContext *s, AVPacket *pkt){    return s->iformat->read_packet(s, pkt);}/**********************************************************//** * Get the number of samples of an audio frame. Return (-1) if error. */static int get_audio_frame_size(AVCodecContext *enc, int size){    int frame_size;    if (enc->frame_size <= 1) {        /* specific hack for pcm codecs because no frame size is           provided */        switch(enc->codec_id) {        case CODEC_ID_PCM_S32LE:        case CODEC_ID_PCM_S32BE:        case CODEC_ID_PCM_U32LE:        case CODEC_ID_PCM_U32BE:            if (enc->channels == 0)                return -1;            frame_size = size / (4 * enc->channels);            break;        case CODEC_ID_PCM_S24LE:        case CODEC_ID_PCM_S24BE:        case CODEC_ID_PCM_U24LE:        case CODEC_ID_PCM_U24BE:        case CODEC_ID_PCM_S24DAUD:            if (enc->channels == 0)                return -1;            frame_size = size / (3 * enc->channels);            break;        case CODEC_ID_PCM_S16LE:        case CODEC_ID_PCM_S16BE:        case CODEC_ID_PCM_U16LE:        case CODEC_ID_PCM_U16BE:            if (enc->channels == 0)                return -1;            frame_size = size / (2 * enc->channels);            break;        case CODEC_ID_PCM_S8:        case CODEC_ID_PCM_U8:        case CODEC_ID_PCM_MULAW:        case CODEC_ID_PCM_ALAW:            if (enc->channels == 0)                return -1;            frame_size = size / (enc->channels);            break;        default:            /* used for example by ADPCM codecs */            if (enc->bit_rate == 0)                return -1;            frame_size = (size * 8 * enc->sample_rate) / enc->bit_rate;            break;        }    } else {        frame_size = enc->frame_size;    }    return frame_size;}/** * Return the frame duration in seconds, return 0 if not available. */static void compute_frame_duration(int *pnum, int *pden, AVStream *st,                                   AVCodecParserContext *pc, AVPacket *pkt){    int frame_size;    *pnum = 0;    *pden = 0;    switch(st->codec->codec_type) {    case CODEC_TYPE_VIDEO:        if(st->time_base.num*1000LL > st->time_base.den){            *pnum = st->time_base.num;            *pden = st->time_base.den;        }else if(st->codec->time_base.num*1000LL > st->codec->time_base.den){            *pnum = st->codec->time_base.num;            *pden = st->codec->time_base.den;            if (pc && pc->repeat_pict) {                *pden *= 2;                *pnum = (*pnum) * (2 + pc->repeat_pict);            }        }        break;    case CODEC_TYPE_AUDIO:        frame_size = get_audio_frame_size(st->codec, pkt->size);        if (frame_size < 0)            break;        *pnum = frame_size;        *pden = st->codec->sample_rate;        break;    default:        break;    }}static int is_intra_only(AVCodecContext *enc){    if(enc->codec_type == CODEC_TYPE_AUDIO){        return 1;    }else if(enc->codec_type == CODEC_TYPE_VIDEO){        switch(enc->codec_id){        case CODEC_ID_MJPEG:        case CODEC_ID_MJPEGB:        case CODEC_ID_LJPEG:        case CODEC_ID_RAWVIDEO:        case CODEC_ID_DVVIDEO:        case CODEC_ID_HUFFYUV:        case CODEC_ID_FFVHUFF:        case CODEC_ID_ASV1:        case CODEC_ID_ASV2:        case CODEC_ID_VCR1:            return 1;        default: break;        }    }    return 0;}static int64_t lsb2full(int64_t lsb, int64_t last_ts, int lsb_bits){    int64_t mask = lsb_bits < 64 ? (1LL<<lsb_bits)-1 : -1LL;    int64_t delta= last_ts - mask/2;    return  ((lsb - delta)&mask) + delta;}static void compute_pkt_fields(AVFormatContext *s, AVStream *st,                               AVCodecParserContext *pc, AVPacket *pkt){    int num, den, presentation_delayed;    /* handle wrapping */    if(st->cur_dts != AV_NOPTS_VALUE){        if(pkt->pts != AV_NOPTS_VALUE)            pkt->pts= lsb2full(pkt->pts, st->cur_dts, st->pts_wrap_bits);        if(pkt->dts != AV_NOPTS_VALUE)            pkt->dts= lsb2full(pkt->dts, st->cur_dts, st->pts_wrap_bits);    }    if (pkt->duration == 0) {        compute_frame_duration(&num, &den, st, pc, pkt);        if (den && num) {            pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num);        }    }    if(is_intra_only(st->codec))        pkt->flags |= PKT_FLAG_KEY;    /* do we have a video B frame ? */    presentation_delayed = 0;    if (st->codec->codec_type == CODEC_TYPE_VIDEO) {        /* XXX: need has_b_frame, but cannot get it if the codec is           not initialized */        if ((   st->codec->codec_id == CODEC_ID_H264             || st->codec->has_b_frames) &&            pc && pc->pict_type != FF_B_TYPE)            presentation_delayed = 1;        /* this may be redundant, but it shouldnt hurt */        if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts > pkt->dts)            presentation_delayed = 1;    }    if(st->cur_dts == AV_NOPTS_VALUE){        if(presentation_delayed) st->cur_dts = -pkt->duration;        else                     st->cur_dts = 0;    }//    av_log(NULL, AV_LOG_DEBUG, "IN delayed:%d pts:%lld, dts:%lld cur_dts:%lld st:%d pc:%p\n", presentation_delayed, pkt->pts, pkt->dts, st->cur_dts, pkt->stream_index, pc);    /* interpolate PTS and DTS if they are not present */    if (presentation_delayed) {        /* DTS = decompression time stamp */        /* PTS = presentation time stamp */        if (pkt->dts == AV_NOPTS_VALUE) {            /* if we know the last pts, use it */            if(st->last_IP_pts != AV_NOPTS_VALUE)                st->cur_dts = pkt->dts = st->last_IP_pts;            else                pkt->dts = st->cur_dts;        } else {            st->cur_dts = pkt->dts;        }        /* this is tricky: the dts must be incremented by the duration           of the frame we are displaying, i.e. the last I or P frame */        if (st->last_IP_duration == 0)            st->cur_dts += pkt->duration;        else            st->cur_dts += st->last_IP_duration;        st->last_IP_duration  = pkt->duration;        st->last_IP_pts= pkt->pts;        /* cannot compute PTS if not present (we can compute it only           by knowing the futur */    } else if(pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE || pkt->duration){        if(pkt->pts != AV_NOPTS_VALUE && pkt->duration){            int64_t old_diff= ABS(st->cur_dts - pkt->duration - pkt->pts);            int64_t new_diff= ABS(st->cur_dts - pkt->pts);            if(old_diff < new_diff && old_diff < (pkt->duration>>3)){                pkt->pts += pkt->duration;//                av_log(NULL, AV_LOG_DEBUG, "id:%d old:%Ld new:%Ld dur:%d cur:%Ld size:%d\n", pkt->stream_index, old_diff, new_diff, pkt->duration, st->cur_dts, pkt->size);            }        }        /* presentation is not delayed : PTS and DTS are the same */        if (pkt->pts == AV_NOPTS_VALUE) {            if (pkt->dts == AV_NOPTS_VALUE) {                pkt->pts = st->cur_dts;                pkt->dts = st->cur_dts;            }            else {                st->cur_dts = pkt->dts;                pkt->pts = pkt->dts;            }        } else {            st->cur_dts = pkt->pts;            pkt->dts = pkt->pts;        }        st->cur_dts += pkt->duration;    }//    av_log(NULL, AV_LOG_DEBUG, "OUTdelayed:%d pts:%lld, dts:%lld cur_dts:%lld\n", presentation_delayed, pkt->pts, pkt->dts, st->cur_dts);    /* update flags */    if (pc) {        pkt->flags = 0;        /* key frame computation */        switch(st->codec->codec_type) {        case CODEC_TYPE_VIDEO:            if (pc->pict_type == FF_I_TYPE)                pkt->flags |= PKT_FLAG_KEY;            break;        case CODEC_TYPE_AUDIO:            pkt->flags |= PKT_FLAG_KEY;            break;        default:

⌨️ 快捷键说明

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