📄 utils.c
字号:
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, "%"PRId64" %"PRId64" %"PRId64" / %"PRId64" %"PRId64" %"PRId64" target:%"PRId64" limit:%"PRId64" start:%"PRId64" 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; } if (target_ts >= ts) { pos_min = pos; ts_min = ts; } } pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max; ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max;#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%"PRIx64" %"PRId64"<=%"PRId64"<=%"PRId64"\n", pos, ts_min, target_ts, ts_max);#endif /* do the seek */ url_fseek(&s->pb, pos, SEEK_SET); av_update_cur_dts(s, st, ts); return 0;}static int av_seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, int flags){ int64_t pos_min, pos_max;#if 0 AVStream *st; if (stream_index < 0) return -1; st= s->streams[stream_index];#endif pos_min = s->data_offset; pos_max = url_fsize(&s->pb) - 1; if (pos < pos_min) pos= pos_min; else if(pos > pos_max) pos= pos_max; url_fseek(&s->pb, pos, SEEK_SET);#if 0 av_update_cur_dts(s, st, ts);#endif return 0;}static int av_seek_frame_generic(AVFormatContext *s, int stream_index, int64_t timestamp, int flags){ int index; 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, flags); 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); av_update_cur_dts(s, st, ie->timestamp); return 0;}/** * Seek to the key frame at timestamp. * 'timestamp' in 'stream_index'. * @param stream_index If stream_index is (-1), a default * stream is selected, and timestamp is automatically converted * from AV_TIME_BASE units to the stream specific time_base. * @param timestamp timestamp in AVStream.time_base units * or if there is no stream specified then in AV_TIME_BASE units * @param flags flags which select direction and seeking mode * @return >= 0 on success */int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags){ int ret; AVStream *st; av_read_frame_flush(s); if(flags & AVSEEK_FLAG_BYTE) return av_seek_frame_byte(s, stream_index, timestamp, flags); if(stream_index < 0){ stream_index= av_find_default_stream_index(s); if(stream_index < 0) return -1; st= s->streams[stream_index]; /* timestamp for default must be expressed in AV_TIME_BASE units */ timestamp = av_rescale(timestamp, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num); } st= s->streams[stream_index]; /* first, we try the format specific seek */ if (s->iformat->read_seek) ret = s->iformat->read_seek(s, stream_index, timestamp, flags); else ret = -1; if (ret >= 0) { return 0; } if(s->iformat->read_timestamp) return av_seek_frame_binary(s, stream_index, timestamp, flags); else return av_seek_frame_generic(s, stream_index, timestamp, flags);}/*******************************************************//** * Returns TRUE if the stream has accurate timings in any stream. * * @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 computes the global bitrate if possible. */static void av_update_stream_timings(AVFormatContext *ic){ int64_t start_time, start_time1, 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) { start_time1= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q); if (start_time1 < start_time) start_time = start_time1; if (st->duration != AV_NOPTS_VALUE) { end_time1 = start_time1 + av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q); if (end_time1 > end_time) end_time = end_time1; } } } if (start_time != MAXINT64) { ic->start_time = start_time; if (end_time != MININT64) { 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) { if(ic->start_time != AV_NOPTS_VALUE) st->start_time = av_rescale_q(ic->start_time, AV_TIME_BASE_Q, st->time_base); if(ic->duration != AV_NOPTS_VALUE) st->duration = av_rescale_q(ic->duration, AV_TIME_BASE_Q, st->time_base); } }}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) { for(i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; duration= av_rescale(8*filesize, st->time_base.den, ic->bit_rate*(int64_t)st->time_base.num); 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 end_time; int64_t filesize, offset, duration; /* free previous packet */ if (ic->cur_st && ic->cur_st->parser) av_free_packet(&ic->cur_pkt); ic->cur_st = NULL; /* flush packet queue */ flush_packet_queue(ic); for(i=0;i<ic->nb_streams;i++) { st = ic->streams[i]; if (st->parser) { av_parser_close(st->parser); st->parser= NULL; } } /* we read the first packets to get the first PTS (not fully accurate, but it is enough now) */ url_fseek(&ic->pb, 0, SEEK_SET); read_size = 0; for(;;) { if (read_size >= DURATION_MAX_READ_SIZE) break; /* if all info is available, we can stop */ for(i = 0;i < ic->nb_streams; i++) { st = ic->streams[i]; if (st->start_time == AV_NOPTS_VALUE) break; } if (i == ic->nb_streams) break; ret = av_read_packet(ic, pkt); if (ret != 0) break; read_size += pkt->size; st = ic->streams[pkt->stream_index]; if (pkt->pts != AV_NOPTS_VALUE) { if (st->start_time == AV_NOPTS_VALUE) st->start_time = pkt->pts; } av_free_packet(pkt); } /* estimate the end time (duration) */ /* XXX: may need to support wrapping */ filesize = ic->file_size; offset = filesize - DURATION_MAX_READ_SIZE; if (offset < 0) offset = 0; url_fseek(&ic->pb, offset, SEEK_SET); read_size = 0; for(;;) { if (read_size >= DURATION_MAX_READ_SIZE) break; /* if all info is available, we can stop */ for(i = 0;i < ic->nb_streams; i++) { st = ic->streams[i]; if (st->duration == AV_NOPTS_VALUE) break; } if (i == ic->nb_streams) break; ret = av_read_packet(ic, pkt); if (ret != 0) break; read_size += pkt->size; st = ic->streams[pkt->stream_index]; if (pkt->pts != AV_NOPTS_VALUE) { end_time = pkt->pts; duration = end_time - st->start_time; if (duration > 0) { if (st->duration == AV_NOPTS_VALUE || st->duration < duration) st->duration = duration; } } av_free_packet(pkt); } fill_all_stream_timings(ic); 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -