av_write_frame
来源:互联网 发布:网络阅卷使用了修正带 编辑:程序博客网 时间:2024/05/19 14:36
av_write_frame
直接将包写进Mux,没有缓存和重新排序,一切都需要用户自己设置。
Packet’s stream_index field must be set to the index of the corresponding stream in s->streams.
The timestamps (pts, dts) must be set to correct values in the stream’s timebase (unless the output format is flagged with the AVFMT_NOTIMESTAMPS flag, then they can be set to AV_NOPTS_VALUE). The dts for subsequent packets passed to this function must be strictly increasing when compared in their respective timebases (unless the output format is flagged with the AVFMT_TS_NONSTRICT, then they merely have to be nondecreasing). duration) should also be set if known.
av_write_frame代码
int av_write_frame(AVFormatContext *s, AVPacket *pkt) { int ret; //对包预处理 ret = prepare_input_packet(s, pkt); if (ret < 0) return ret; //空包,flush if (!pkt) { if (s->oformat->flags & AVFMT_ALLOW_FLUSH) { if (!s->internal->header_written) { ret = s->internal->write_header_ret ? s->internal->write_header_ret : write_header_internal(s); if (ret < 0) return ret; } ret = s->oformat->write_packet(s, NULL); if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS) avio_flush(s->pb); if (ret >= 0 && s->pb && s->pb->error < 0) ret = s->pb->error; return ret; } return 1; } //计算包信息 #if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX ret = compute_muxer_pkt_fields(s, s->streams[pkt->stream_index], pkt); if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) return ret; #endif //写包 ret = write_packet(s, pkt); if (ret >= 0 && s->pb && s->pb->error < 0) ret = s->pb->error; if (ret >= 0) s->streams[pkt->stream_index]->nb_frames++; return ret; }
prepare_input_packet代码
(检查流通道 和 包的pts,dts是否符合)
static int prepare_input_packet(AVFormatContext *s, AVPacket *pkt) { int ret; //检查流通道 ret = check_packet(s, pkt); if (ret < 0) return ret; //检查PTS , DTS #if !FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX /* sanitize the timestamps */ if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { AVStream *st = s->streams[pkt->stream_index]; /* when there is no reordering (so dts is equal to pts), but * only one of them is set, set the other as well */ if (!st->internal->reorder) { if (pkt->pts == AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE) pkt->pts = pkt->dts; if (pkt->dts == AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE) pkt->dts = pkt->pts; } /* check that the timestamps are set */ if (pkt->pts == AV_NOPTS_VALUE || pkt->dts == AV_NOPTS_VALUE) { av_log(s, AV_LOG_ERROR, "Timestamps are unset in a packet for stream %d\n", st->index); return AVERROR(EINVAL); } /* check that the dts are increasing (or at least non-decreasing, * if the format allows it */ if (st->cur_dts != AV_NOPTS_VALUE && ((!(s->oformat->flags & AVFMT_TS_NONSTRICT) && st->cur_dts >= pkt->dts) || st->cur_dts > pkt->dts)) { av_log(s, AV_LOG_ERROR, "Application provided invalid, non monotonically increasing " "dts to muxer in stream %d: %" PRId64 " >= %" PRId64 "\n", st->index, st->cur_dts, pkt->dts); return AVERROR(EINVAL); } if (pkt->pts < pkt->dts) { av_log(s, AV_LOG_ERROR, "pts %" PRId64 " < dts %" PRId64 " in stream %d\n", pkt->pts, pkt->dts, st->index); return AVERROR(EINVAL); } } #endif return 0; }
compute_muxer_pkt_fields 代码
(计算duration ,pts,dts等)
static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket *pkt) { int delay = FFMAX(st->codecpar->video_delay, st->internal->avctx->max_b_frames > 0); int num, den, i; int frame_size; if (!s->internal->missing_ts_warning && !(s->oformat->flags & AVFMT_NOTIMESTAMPS) && (pkt->pts == AV_NOPTS_VALUE || pkt->dts == AV_NOPTS_VALUE)) { av_log(s, AV_LOG_WARNING, "Timestamps are unset in a packet for stream %d. " "This is deprecated and will stop working in the future. " "Fix your code to set the timestamps properly\n", st->index); s->internal->missing_ts_warning = 1; } if (s->debug & FF_FDEBUG_TS) av_log(s, AV_LOG_TRACE, "compute_muxer_pkt_fields: pts:%s dts:%s cur_dts:%s b:%d size:%d st:%d\n", av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts), delay, pkt->size, pkt->stream_index); if (pkt->duration < 0 && st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) { av_log(s, AV_LOG_WARNING, "Packet with invalid duration %"PRId64" in stream %d\n", pkt->duration, pkt->stream_index); pkt->duration = 0; } /* duration field */ if (pkt->duration == 0) { ff_compute_frame_duration(s, &num, &den, st, NULL, pkt); if (den && num) { pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den * st->codec->ticks_per_frame, den * (int64_t)st->time_base.num); } } if (pkt->pts == AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && delay == 0) pkt->pts = pkt->dts; //XXX/FIXME this is a temporary hack until all encoders output pts if ((pkt->pts == 0 || pkt->pts == AV_NOPTS_VALUE) && pkt->dts == AV_NOPTS_VALUE && !delay) { static int warned; if (!warned) { av_log(s, AV_LOG_WARNING, "Encoder did not produce proper pts, making some up.\n"); warned = 1; } pkt->dts = // pkt->pts= st->cur_dts; pkt->pts = st->priv_pts->val; } //calculate dts from pts if (pkt->pts != AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY) { st->pts_buffer[0] = pkt->pts; for (i = 1; i < delay + 1 && st->pts_buffer[i] == AV_NOPTS_VALUE; i++) st->pts_buffer[i] = pkt->pts + (i - delay - 1) * pkt->duration; for (i = 0; i<delay && st->pts_buffer[i] > st->pts_buffer[i + 1]; i++) FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i + 1]); pkt->dts = st->pts_buffer[0]; } if (st->cur_dts && st->cur_dts != AV_NOPTS_VALUE && ((!(s->oformat->flags & AVFMT_TS_NONSTRICT) && st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE && st->codecpar->codec_type != AVMEDIA_TYPE_DATA && st->cur_dts >= pkt->dts) || st->cur_dts > pkt->dts)) { av_log(s, AV_LOG_ERROR, "Application provided invalid, non monotonically increasing dts to muxer in stream %d: %s >= %s\n", st->index, av_ts2str(st->cur_dts), av_ts2str(pkt->dts)); return AVERROR(EINVAL); } if (pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts < pkt->dts) { av_log(s, AV_LOG_ERROR, "pts (%s) < dts (%s) in stream %d\n", av_ts2str(pkt->pts), av_ts2str(pkt->dts), st->index); return AVERROR(EINVAL); } if (s->debug & FF_FDEBUG_TS) av_log(s, AV_LOG_TRACE, "av_write_frame: pts2:%s dts2:%s\n", av_ts2str(pkt->pts), av_ts2str(pkt->dts)); st->cur_dts = pkt->dts; st->priv_pts->val = pkt->dts; /* update pts */ switch (st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: frame_size = (pkt->flags & AV_PKT_FLAG_UNCODED_FRAME) ? ((AVFrame *)pkt->data)->nb_samples : av_get_audio_frame_duration(st->codec, pkt->size); /* HACK/FIXME, we skip the initial 0 size packets as they are most * likely equal to the encoder delay, but it would be better if we * had the real timestamps from the encoder */ if (frame_size >= 0 && (pkt->size || st->priv_pts->num != st->priv_pts->den >> 1 || st->priv_pts->val)) { frac_add(st->priv_pts, (int64_t)st->time_base.den * frame_size); } break; case AVMEDIA_TYPE_VIDEO: frac_add(st->priv_pts, (int64_t)st->time_base.den * st->time_base.num); break; } return 0; }
write_frame代码
写包调用了AVOutputFormat 的 write_packet 。与write_header类似,具体的写包实现在各个封装的 AVOutputFormat 中。
static int write_packet(AVFormatContext *s, AVPacket *pkt) { int ret, did_split; if (s->output_ts_offset) { AVStream *st = s->streams[pkt->stream_index]; int64_t offset = av_rescale_q(s->output_ts_offset, AV_TIME_BASE_Q, st->time_base); if (pkt->dts != AV_NOPTS_VALUE) pkt->dts += offset; if (pkt->pts != AV_NOPTS_VALUE) pkt->pts += offset; } if (s->avoid_negative_ts > 0) { AVStream *st = s->streams[pkt->stream_index]; int64_t offset = st->mux_ts_offset; int64_t ts = s->internal->avoid_negative_ts_use_pts ? pkt->pts : pkt->dts; if (s->internal->offset == AV_NOPTS_VALUE && ts != AV_NOPTS_VALUE && (ts < 0 || s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO)) { s->internal->offset = -ts; s->internal->offset_timebase = st->time_base; } if (s->internal->offset != AV_NOPTS_VALUE && !offset) { offset = st->mux_ts_offset = av_rescale_q_rnd(s->internal->offset, s->internal->offset_timebase, st->time_base, AV_ROUND_UP); } if (pkt->dts != AV_NOPTS_VALUE) pkt->dts += offset; if (pkt->pts != AV_NOPTS_VALUE) pkt->pts += offset; if (s->internal->avoid_negative_ts_use_pts) { if (pkt->pts != AV_NOPTS_VALUE && pkt->pts < 0) { av_log(s, AV_LOG_WARNING, "failed to avoid negative " "pts %s in stream %d.\n" "Try -avoid_negative_ts 1 as a possible workaround.\n", av_ts2str(pkt->dts), pkt->stream_index ); } } else { av_assert2(pkt->dts == AV_NOPTS_VALUE || pkt->dts >= 0 || s->max_interleave_delta > 0); if (pkt->dts != AV_NOPTS_VALUE && pkt->dts < 0) { av_log(s, AV_LOG_WARNING, "Packets poorly interleaved, failed to avoid negative " "timestamp %s in stream %d.\n" "Try -max_interleave_delta 0 as a possible workaround.\n", av_ts2str(pkt->dts), pkt->stream_index ); } } } did_split = av_packet_split_side_data(pkt); if (!s->internal->header_written) { ret = s->internal->write_header_ret ? s->internal->write_header_ret : write_header_internal(s); if (ret < 0) goto fail; } if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) { AVFrame *frame = (AVFrame *)pkt->data; av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE); ret = s->oformat->write_uncoded_frame(s, pkt->stream_index, &frame, 0); av_frame_free(&frame); } else { ret = s->oformat->write_packet(s, pkt); } if (s->pb && ret >= 0) { if (s->flush_packets && s->flags & AVFMT_FLAG_FLUSH_PACKETS) avio_flush(s->pb); if (s->pb->error < 0) ret = s->pb->error; } fail: if (did_split) av_packet_merge_side_data(pkt); return ret; }
- av_write_frame
- av_write_frame()
- av_write_frame 与 av_interleaved_write_frame
- av_write_frame 与 av_interleaved_write_frame
- av_write_frame 与 av_interleaved_write_frame
- FFmpeg源代码简单分析:av_write_frame()
- ffmpeg源码跟踪笔记之av_write_frame 与 av_interleaved_write_frame
- ffmpeg——av_write_frame/av_interleaved_write_frame写文件包
- ffmpeg源码简析(六)编码-av_write_frame(),av_write_trailer()
- Mahout推荐算法API详解
- 对象去重
- 排序算法(python)-快速排序
- ViewPager加载图片自动无限轮播
- Android 避免app切换黑屏
- av_write_frame
- Redis和图形工具在windows下安装过程
- Fingerprint指纹识别学习
- Mysql SQLyog导入导出csv文件
- 网络画板的文本编辑器也是markdown编辑器吗?
- EXT JS 网格 控制全选监听事件
- 求给定两字符串的最长相同子串
- 百度地图不显示问题
- 人脸识别部分内存调用优化