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

📄 utils.c

📁 F:图像处理资料264264书籍ffmpeg-0.4.9-pre1VideoStream.rar 一个视频解压缩源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
                index++; //index points to next instead of previous entry, maybe nonexistant                ie= &st->index_entries[index];            }else                assert(index==0);                            if(index != st->nb_index_entries){                assert(index < st->nb_index_entries);                memmove(entries + index + 1, entries + index, sizeof(AVIndexEntry)*(st->nb_index_entries - index));            }            st->nb_index_entries++;        }else{            if(ie->pos == pos && distance < ie->min_distance) //dont reduce the distance                distance= ie->min_distance;        }    }else{        index= st->nb_index_entries++;        ie= &entries[index];    }        ie->pos = pos;    ie->timestamp = timestamp;    ie->min_distance= distance;    ie->flags = flags;        return index;}/* build an index for raw streams using a parser */static void av_build_index_raw(AVFormatContext *s){    AVPacket pkt1, *pkt = &pkt1;    int ret;    AVStream *st;    st = s->streams[0];    av_read_frame_flush(s);    url_fseek(&s->pb, s->data_offset, SEEK_SET);    for(;;) {        ret = av_read_frame(s, pkt);        if (ret < 0)            break;        if (pkt->stream_index == 0 && st->parser &&            (pkt->flags & PKT_FLAG_KEY)) {            int64_t dts= av_rescale(pkt->dts, st->time_base.den, AV_TIME_BASE*(int64_t)st->time_base.num);            av_add_index_entry(st, st->parser->frame_offset, dts,                             0, AVINDEX_KEYFRAME);        }        av_free_packet(pkt);    }}/* return TRUE if we deal with a raw stream (raw codec data and   parsing needed) */static int is_raw_stream(AVFormatContext *s){    AVStream *st;    if (s->nb_streams != 1)        return 0;    st = s->streams[0];    if (!st->need_parsing)        return 0;    return 1;}/* return the largest index entry whose timestamp is <=   wanted_timestamp */int av_index_search_timestamp(AVStream *st, int wanted_timestamp){    AVIndexEntry *entries= st->index_entries;    int nb_entries= st->nb_index_entries;    int a, b, m;    int64_t timestamp;    if (nb_entries <= 0)        return -1;        a = 0;    b = nb_entries - 1;    while (a < b) {        m = (a + b + 1) >> 1;        timestamp = entries[m].timestamp;        if (timestamp > wanted_timestamp) {            b = m - 1;        } else {            a = m;        }    }    return a;}#define DEBUG_SEEK/** * Does a binary search using av_index_search_timestamp() and AVCodec.read_timestamp(). * this isnt supposed to be called directly by a user application, but by demuxers * @param target_ts target timestamp in the time base of the given stream * @param stream_index stream number */int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts){    AVInputFormat *avif= s->iformat;    int64_t pos_min, pos_max, pos, pos_limit;    int64_t ts_min, ts_max, ts;    int64_t start_pos;    int index, no_change, i;    AVStream *st;    if (stream_index < 0)        return -1;    #ifdef DEBUG_SEEK    av_log(s, AV_LOG_DEBUG, "read_seek: %d %lld\n", stream_index, target_ts);#endif    ts_max=    ts_min= AV_NOPTS_VALUE;    pos_limit= -1; //gcc falsely says it may be uninitalized    st= s->streams[stream_index];    if(st->index_entries){        AVIndexEntry *e;        index= av_index_search_timestamp(st, target_ts);        e= &st->index_entries[index];        if(e->timestamp <= target_ts || e->pos == e->min_distance){            pos_min= e->pos;            ts_min= e->timestamp;#ifdef DEBUG_SEEK        av_log(s, AV_LOG_DEBUG, "using cached pos_min=0x%llx dts_min=%lld\n",                pos_min,ts_min);#endif        }else{            assert(index==0);        }        index++;        if(index < st->nb_index_entries){            e= &st->index_entries[index];            assert(e->timestamp >= target_ts);            pos_max= e->pos;            ts_max= e->timestamp;            pos_limit= pos_max - e->min_distance;#ifdef DEBUG_SEEK        av_log(s, AV_LOG_DEBUG, "using cached pos_max=0x%llx pos_limit=0x%llx dts_max=%lld\n",                pos_max,pos_limit, ts_max);#endif        }    }    if(ts_min == AV_NOPTS_VALUE){        pos_min = s->data_offset;        ts_min = avif->read_timestamp(s, stream_index, &pos_min, INT64_MAX);        if (ts_min == AV_NOPTS_VALUE)            return -1;    }    if(ts_max == AV_NOPTS_VALUE){        int step= 1024;        pos_max = url_filesize(url_fileno(&s->pb)) - 1;        do{            pos_max -= step;            ts_max = avif->read_timestamp(s, stream_index, &pos_max, pos_max + step);            step += step;        }while(ts_max == AV_NOPTS_VALUE && pos_max >= step);        if (ts_max == AV_NOPTS_VALUE)            return -1;                for(;;){            int64_t tmp_pos= pos_max + 1;            int64_t tmp_ts= avif->read_timestamp(s, stream_index, &tmp_pos, INT64_MAX);            if(tmp_ts == AV_NOPTS_VALUE)                break;            ts_max= tmp_ts;            pos_max= tmp_pos;        }        pos_limit= pos_max;    }    no_change=0;    while (pos_min < pos_limit) {#ifdef DEBUG_SEEK        av_log(s, AV_LOG_DEBUG, "pos_min=0x%llx pos_max=0x%llx dts_min=%lld dts_max=%lld\n",                pos_min, pos_max,               ts_min, ts_max);#endif        assert(pos_limit <= pos_max);        if(no_change==0){            int64_t approximate_keyframe_distance= pos_max - pos_limit;            // interpolate position (better than dichotomy)            pos = (int64_t)((double)(pos_max - pos_min) *                            (double)(target_ts - ts_min) /                            (double)(ts_max - ts_min)) + pos_min - approximate_keyframe_distance;        }else if(no_change==1){            // bisection, if interpolation failed to change min or max pos last time            pos = (pos_min + pos_limit)>>1;        }else{            // linear search if bisection failed, can only happen if there are very few or no keframes between min/max            pos=pos_min;        }        if(pos <= pos_min)            pos= pos_min + 1;        else if(pos > pos_limit)            pos= pos_limit;        start_pos= pos;        ts = avif->read_timestamp(s, stream_index, &pos, INT64_MAX); //may pass pos_limit instead of -1        if(pos == pos_max)            no_change++;        else            no_change=0;#ifdef DEBUG_SEEKav_log(s, AV_LOG_DEBUG, "%Ld %Ld %Ld / %Ld %Ld %Ld target:%Ld limit:%Ld start:%Ld noc:%d\n", pos_min, pos, pos_max, ts_min, ts, ts_max, target_ts, pos_limit, start_pos, no_change);#endif        assert(ts != AV_NOPTS_VALUE);        if (target_ts < ts) {            pos_limit = start_pos - 1;            pos_max = pos;            ts_max = ts;        } else {            pos_min = pos;            ts_min = ts;            /* check if we are lucky */            if (target_ts == ts)                break;        }    }        pos = pos_min;#ifdef DEBUG_SEEK    pos_min = pos;    ts_min = avif->read_timestamp(s, stream_index, &pos_min, INT64_MAX);    pos_min++;    ts_max = avif->read_timestamp(s, stream_index, &pos_min, INT64_MAX);    av_log(s, AV_LOG_DEBUG, "pos=0x%llx %lld<=%lld<=%lld\n",            pos, ts_min, target_ts, ts_max);#endif    /* do the seek */    url_fseek(&s->pb, pos, SEEK_SET);    ts= av_rescale(ts_min, AV_TIME_BASE*(int64_t)st->time_base.num, st->time_base.den);    for(i = 0; i < s->nb_streams; i++) {        st = s->streams[i];        st->cur_dts = av_rescale(ts, st->time_base.den, AV_TIME_BASE*(int64_t)st->time_base.num);    }    return 0;}static int av_seek_frame_generic(AVFormatContext *s,                                  int stream_index, int64_t timestamp){    int index, i;    AVStream *st;    AVIndexEntry *ie;    if (!s->index_built) {        if (is_raw_stream(s)) {            av_build_index_raw(s);        } else {            return -1;        }        s->index_built = 1;    }    st = s->streams[stream_index];    index = av_index_search_timestamp(st, timestamp);    if (index < 0)        return -1;    /* now we have found the index, we can seek */    ie = &st->index_entries[index];    av_read_frame_flush(s);    url_fseek(&s->pb, ie->pos, SEEK_SET);        timestamp= av_rescale(ie->timestamp, AV_TIME_BASE*(int64_t)st->time_base.num, st->time_base.den);    for(i = 0; i < s->nb_streams; i++) {        st = s->streams[i];        st->cur_dts = av_rescale(timestamp, st->time_base.den, AV_TIME_BASE*(int64_t)st->time_base.num);    }    return 0;}/** * Seek to the key frame just before the frame at timestamp * 'timestamp' in 'stream_index'. * @param stream_index If stream_index is (-1), a default * stream is selected * @param timestamp timestamp in AV_TIME_BASE units * @return >= 0 on success */int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp){    int ret;    AVStream *st;        av_read_frame_flush(s);        if(stream_index < 0){        stream_index= av_find_default_stream_index(s);        if(stream_index < 0)            return -1;    }    st= s->streams[stream_index];    timestamp = av_rescale(timestamp, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num);    /* first, we try the format specific seek */    if (s->iformat->read_seek)        ret = s->iformat->read_seek(s, stream_index, timestamp);    else        ret = -1;    if (ret >= 0) {        return 0;    }    if(s->iformat->read_timestamp)        return av_seek_frame_binary(s, stream_index, timestamp);    else        return av_seek_frame_generic(s, stream_index, timestamp);}/*******************************************************//* return TRUE if the stream has accurate timings for at least one component */static int av_has_timings(AVFormatContext *ic){    int i;    AVStream *st;    for(i = 0;i < ic->nb_streams; i++) {        st = ic->streams[i];        if (st->start_time != AV_NOPTS_VALUE &&            st->duration != AV_NOPTS_VALUE)            return 1;    }    return 0;}/* estimate the stream timings from the one of each components. Also   compute the global bitrate if possible */static void av_update_stream_timings(AVFormatContext *ic){    int64_t start_time, end_time, end_time1;    int i;    AVStream *st;    start_time = MAXINT64;    end_time = MININT64;    for(i = 0;i < ic->nb_streams; i++) {        st = ic->streams[i];        if (st->start_time != AV_NOPTS_VALUE) {            if (st->start_time < start_time)                start_time = st->start_time;            if (st->duration != AV_NOPTS_VALUE) {                end_time1 = st->start_time + st->duration;                if (end_time1 > end_time)                    end_time = end_time1;            }        }    }    if (start_time != MAXINT64) {        ic->start_time = start_time;        if (end_time != MAXINT64) {            ic->duration = end_time - start_time;            if (ic->file_size > 0) {                /* compute the bit rate */                ic->bit_rate = (double)ic->file_size * 8.0 * AV_TIME_BASE /                     (double)ic->duration;            }        }    }}static void fill_all_stream_timings(AVFormatContext *ic){    int i;    AVStream *st;    av_update_stream_timings(ic);    for(i = 0;i < ic->nb_streams; i++) {        st = ic->streams[i];        if (st->start_time == AV_NOPTS_VALUE) {            st->start_time = ic->start_time;            st->duration = ic->duration;        }    }}static void av_estimate_timings_from_bit_rate(AVFormatContext *ic){    int64_t filesize, duration;    int bit_rate, i;    AVStream *st;    /* if bit_rate is already set, we believe it */    if (ic->bit_rate == 0) {        bit_rate = 0;        for(i=0;i<ic->nb_streams;i++) {            st = ic->streams[i];            bit_rate += st->codec.bit_rate;        }        ic->bit_rate = bit_rate;    }    /* if duration is already set, we believe it */    if (ic->duration == AV_NOPTS_VALUE &&         ic->bit_rate != 0 &&         ic->file_size != 0)  {        filesize = ic->file_size;        if (filesize > 0) {            duration = (int64_t)((8 * AV_TIME_BASE * (double)filesize) / (double)ic->bit_rate);            for(i = 0; i < ic->nb_streams; i++) {                st = ic->streams[i];                if (st->start_time == AV_NOPTS_VALUE ||                    st->duration == AV_NOPTS_VALUE) {                    st->start_time = 0;                    st->duration = duration;                }            }        }    }}#define DURATION_MAX_READ_SIZE 250000/* only usable for MPEG-PS streams */static void av_estimate_timings_from_pts(AVFormatContext *ic){    AVPacket pkt1, *pkt = &pkt1;    AVStream *st;    int read_size, i, ret;    int64_t start_time, end_time, end_time1;    int64_t filesize, offset, duration;

⌨️ 快捷键说明

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