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

📄 utils.c

📁 mpeg4 video codec mpeg4 video codec
💻 C
📖 第 1 页 / 共 5 页
字号:
                        if (pkt->size)                            goto got_packet;                    }                }                /* no more packets: really terminates parsing */                return ret;            }                        st = s->streams[s->cur_pkt.stream_index];            s->cur_st = st;            s->cur_ptr = s->cur_pkt.data;            s->cur_len = s->cur_pkt.size;            if (st->need_parsing && !st->parser) {                st->parser = av_parser_init(st->codec->codec_id);                if (!st->parser) {                    /* no parser available : just output the raw packets */                    st->need_parsing = 0;                }else if(st->need_parsing == 2){                    st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;                }            }        }    }}/** * Return the next frame of a stream. * * The returned packet is valid * until the next av_read_frame() or until av_close_input_file() and * must be freed with av_free_packet. For video, the packet contains * exactly one frame. For audio, it contains an integer number of * frames if each frame has a known fixed size (e.g. PCM or ADPCM * data). If the audio frames have a variable size (e.g. MPEG audio), * then it contains one frame. *  * pkt->pts, pkt->dts and pkt->duration are always set to correct * values in AV_TIME_BASE unit (and guessed if the format cannot * provided them). pkt->pts can be AV_NOPTS_VALUE if the video format * has B frames, so it is better to rely on pkt->dts if you do not * decompress the payload. * * @return 0 if OK, < 0 if error or end of file. */int av_read_frame(AVFormatContext *s, AVPacket *pkt){    AVPacketList *pktl;    int eof=0;    const int genpts= s->flags & AVFMT_FLAG_GENPTS;    for(;;){    pktl = s->packet_buffer;    if (pktl) {            AVPacket *next_pkt= &pktl->pkt;            AVStream *st= s->streams[ next_pkt->stream_index ];            if(genpts && next_pkt->dts != AV_NOPTS_VALUE){                while(pktl && next_pkt->pts == AV_NOPTS_VALUE){                    if(   pktl->pkt.stream_index == next_pkt->stream_index                        && next_pkt->dts < pktl->pkt.dts                       && pktl->pkt.pts != pktl->pkt.dts //not b frame                       /*&& pktl->pkt.dts != AV_NOPTS_VALUE*/){                        next_pkt->pts= pktl->pkt.dts;                    }                    pktl= pktl->next;                }                pktl = s->packet_buffer;            }                        if(   next_pkt->pts != AV_NOPTS_VALUE                || next_pkt->dts == AV_NOPTS_VALUE                || !genpts || eof){        /* read packet from packet buffer, if there is data */                *pkt = *next_pkt;        s->packet_buffer = pktl->next;        av_free(pktl);        return 0;            }        }        if(genpts){            AVPacketList **plast_pktl= &s->packet_buffer;            int ret= av_read_frame_internal(s, pkt);            if(ret<0){                if(pktl && ret != -EAGAIN){                    eof=1;                    continue;                }else                    return ret;            }                        /* duplicate the packet */            if (av_dup_packet(pkt) < 0)                return AVERROR_NOMEM;            while(*plast_pktl) plast_pktl= &(*plast_pktl)->next; //FIXME maybe maintain pointer to the last?                        pktl = av_mallocz(sizeof(AVPacketList));            if (!pktl)                return AVERROR_NOMEM;                /* add the packet in the buffered packet list */            *plast_pktl = pktl;            pktl->pkt= *pkt;                } else {            assert(!s->packet_buffer);        return av_read_frame_internal(s, pkt);    }}}/* XXX: suppress the packet queue */static void flush_packet_queue(AVFormatContext *s){    AVPacketList *pktl;    for(;;) {        pktl = s->packet_buffer;        if (!pktl)             break;        s->packet_buffer = pktl->next;        av_free_packet(&pktl->pkt);        av_free(pktl);    }}/*******************************************************//* seek support */int av_find_default_stream_index(AVFormatContext *s){    int i;    AVStream *st;    if (s->nb_streams <= 0)        return -1;    for(i = 0; i < s->nb_streams; i++) {        st = s->streams[i];        if (st->codec->codec_type == CODEC_TYPE_VIDEO) {            return i;        }    }    return 0;}/** * Flush the frame reader. */static void av_read_frame_flush(AVFormatContext *s){    AVStream *st;    int i;    flush_packet_queue(s);    /* free previous packet */    if (s->cur_st) {        if (s->cur_st->parser)            av_free_packet(&s->cur_pkt);        s->cur_st = NULL;    }    /* fail safe */    s->cur_ptr = NULL;    s->cur_len = 0;        /* for each stream, reset read state */    for(i = 0; i < s->nb_streams; i++) {        st = s->streams[i];                if (st->parser) {            av_parser_close(st->parser);            st->parser = NULL;        }        st->last_IP_pts = AV_NOPTS_VALUE;        st->cur_dts = 0; /* we set the current DTS to an unspecified origin */    }}/** * Updates cur_dts of all streams based on given timestamp and AVStream. * * Stream ref_st unchanged, others set cur_dts in their native timebase * only needed for timestamp wrapping or if (dts not set and pts!=dts) * @param timestamp new dts expressed in time_base of param ref_st * @param ref_st reference stream giving time_base of param timestamp */static void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp){    int i;    for(i = 0; i < s->nb_streams; i++) {        AVStream *st = s->streams[i];        st->cur_dts = av_rescale(timestamp,                                  st->time_base.den * (int64_t)ref_st->time_base.num,                                 st->time_base.num * (int64_t)ref_st->time_base.den);    }}/** * Add a index entry into a sorted list updateing if it is already there. * * @param timestamp timestamp in the timebase of the given stream */int av_add_index_entry(AVStream *st,                            int64_t pos, int64_t timestamp, int distance, int flags){    AVIndexEntry *entries, *ie;    int index;        if((unsigned)st->nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))        return -1;        entries = av_fast_realloc(st->index_entries,                              &st->index_entries_allocated_size,                              (st->nb_index_entries + 1) *                               sizeof(AVIndexEntry));    if(!entries)        return -1;    st->index_entries= entries;    index= av_index_search_timestamp(st, timestamp, AVSEEK_FLAG_ANY);    if(index<0){        index= st->nb_index_entries++;        ie= &entries[index];        assert(index==0 || ie[-1].timestamp < timestamp);    }else{        ie= &entries[index];        if(ie->timestamp != timestamp){            if(ie->timestamp <= timestamp)                return -1;            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;    }    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)) {            av_add_index_entry(st, st->parser->frame_offset, pkt->dts,                             0, AVINDEX_KEYFRAME);        }        av_free_packet(pkt);    }}/** * Returns 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;}/** * Gets the index for a specific timestamp. * @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond to  *                 the timestamp which is <= the requested one, if backward is 0  *                 then it will be >= *              if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise * @return < 0 if no such timestamp could be found */int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp,                              int flags){    AVIndexEntry *entries= st->index_entries;    int nb_entries= st->nb_index_entries;    int a, b, m;    int64_t timestamp;    a = - 1;    b = nb_entries;    while (b - a > 1) {        m = (a + b) >> 1;        timestamp = entries[m].timestamp;        if(timestamp >= wanted_timestamp)            b = m;        if(timestamp <= wanted_timestamp)            a = m;    }    m= (flags & AVSEEK_FLAG_BACKWARD) ? a : b;        if(!(flags & AVSEEK_FLAG_ANY)){        while(m>=0 && m<nb_entries && !(entries[m].flags & AVINDEX_KEYFRAME)){            m += (flags & AVSEEK_FLAG_BACKWARD) ? -1 : 1;        }    }    if(m == nb_entries)         return -1;    return  m;}#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, int flags){    AVInputFormat *avif= s->iformat;    int64_t pos_min, pos_max, pos, pos_limit;    int64_t ts_min, ts_max, ts;    int64_t start_pos, filesize;    int index, no_change;    AVStream *st;    if (stream_index < 0)        return -1;    #ifdef DEBUG_SEEK    av_log(s, AV_LOG_DEBUG, "read_seek: %d %"PRId64"\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, flags | AVSEEK_FLAG_BACKWARD); //FIXME whole func must be checked for non keyframe entries in index case, especially read_timestamp()        index= FFMAX(index, 0);        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%"PRIx64" dts_min=%"PRId64"\n",               pos_min,ts_min);#endif        }else{            assert(index==0);        }                index= av_index_search_timestamp(st, target_ts, flags & ~AVSEEK_FLAG_BACKWARD);         assert(index < st->nb_index_entries);        if(index >= 0){            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%"PRIx64" pos_limit=0x%"PRIx64" dts_max=%"PRId64"\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;        filesize = url_fsize(&s->pb);        pos_max = filesize - 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;            if(tmp_pos >= filesize)                break;        }        pos_limit= pos_max;    }    no_change=0;    while (pos_min < pos_limit) {#ifdef DEBUG_SEEK        av_log(s, AV_LOG_DEBUG, "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%"PRId64" dts_max=%"PRId64"\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 = av_rescale(target_ts - ts_min, pos_max - pos_min, 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;

⌨️ 快捷键说明

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