📄 utils.c
字号:
/** * 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 + -