This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 5c557dd5d554c0510de36a12d3dec1e8c84efc9d Author: Gyan Doshi <[email protected]> AuthorDate: Tue Feb 7 18:45:30 2023 +0530 Commit: Gyan Doshi <[email protected]> CommitDate: Tue May 5 12:54:36 2026 +0530 avformat: add av_program_copy() Helper to transfer programs from one muxing context to another. --- doc/APIchanges | 3 ++ libavformat/avformat.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/avformat.h | 31 +++++++++++++++ libavformat/version.h | 2 +- 4 files changed, 140 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 4b7f21aca6..94fec16cae 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2025-03-28 API changes, most recent first: +2026-05-05 - xxxxxxxxxxx - lavf 62.15.100 - avformat.h + Add av_program_copy(). + 2026-05-05 - xxxxxxxxxxx - lavf 62.14.100 - avformat.h Add av_program_add_stream_index2(). diff --git a/libavformat/avformat.c b/libavformat/avformat.c index f4bb4dbac0..3bc79a3592 100644 --- a/libavformat/avformat.c +++ b/libavformat/avformat.c @@ -335,6 +335,111 @@ void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned idx) return; } +int av_program_copy(AVFormatContext *dst, const AVFormatContext *src, int progid, int flags) +{ + const AVProgram *src_prog = NULL; + AVProgram *dst_prog = NULL; + int ret, idx = -1, match = -1; + int overwrite = flags & AVFMT_PROGCOPY_OVERWRITE; + + if ((flags & AVFMT_PROGCOPY_MATCH_BY_ID) && (flags & AVFMT_PROGCOPY_MATCH_BY_INDEX)) + return AVERROR(EINVAL); + else if (flags & AVFMT_PROGCOPY_MATCH_BY_ID) + match = 0; + else if (flags & AVFMT_PROGCOPY_MATCH_BY_INDEX) + match = 1; + + for (unsigned i = 0; i < src->nb_programs; i++) { + if (src->programs[i]->id == progid) { + if (src_prog) { + av_log(dst, AV_LOG_ERROR, "multiple programs found in source with same id 0x%04x. Not copying.\n", progid); + return AVERROR(EINVAL); + } else { + src_prog = src->programs[i]; + } + } + } + + if (!src_prog) { + av_log(dst, AV_LOG_ERROR, "source program not found: id=0x%04x\n", progid); + return AVERROR(EINVAL); + } + + for (unsigned i = 0; i < dst->nb_programs; i++) { + if (dst->programs[i]->id == progid) { + if (idx > -1) { + av_log(dst, AV_LOG_ERROR, "multiple programs found in target with same id 0x%04x. Not copying.\n", progid); + return AVERROR(EINVAL); + } else { + idx = i; + } + } + } + + if (idx >= 0 && !overwrite) + return AVERROR(EEXIST); + + av_log(dst, AV_LOG_TRACE, "%s program: id=0x%04x\n", idx >= 0 ? "overwriting" : "copying", progid); + + if (idx >= 0) { + dst_prog = dst->programs[idx]; + av_dict_free(&dst_prog->metadata); + av_freep(&dst_prog->stream_index); + dst_prog->nb_stream_indexes = 0; + } else { + dst_prog = av_new_program(dst, progid); + if (!dst_prog) + return AVERROR(ENOMEM); + } + + /* public fields */ + dst_prog->id = src_prog->id; + dst_prog->flags = src_prog->flags; + dst_prog->discard = src_prog->discard; + dst_prog->program_num = src_prog->program_num; + dst_prog->pmt_pid = src_prog->pmt_pid; + dst_prog->pcr_pid = src_prog->pcr_pid; + dst_prog->pmt_version = src_prog->pmt_version; + + if (match == -1 && src->nb_streams) { + match = 0; + for (unsigned i = 0; i < src->nb_streams && !match; i++) { + int src_id = src->streams[i]->id; + if (!src_id) { + match = 1; + break; + } + for (unsigned j=i+1; j < src->nb_streams; j++) { + int sib_id = src->streams[j]->id; + if (src_id == sib_id) { + match = 1; + break; + } + } + } + } + + for (unsigned i = 0; i < dst->nb_streams; i++) { + int dst_val = match ? i : dst->streams[i]->id; + + for (unsigned j = 0; j < src_prog->nb_stream_indexes; j++) { + int src_val = match ? src_prog->stream_index[j] : src->streams[src_prog->stream_index[j]]->id; + + if (dst_val == src_val) { + ret = av_program_add_stream_index2(dst, dst_prog->id, i); + if (ret < 0) + return ret; + } + } + } + + ret = av_dict_copy(&dst_prog->metadata, src_prog->metadata, 0); + if (ret < 0) + return ret; + + return 0; +} + AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s) { for (unsigned i = 0; i < ic->nb_programs; i++) { diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 33289e3b89..4bc4ada940 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2069,6 +2069,37 @@ int avformat_stream_group_add_stream(AVStreamGroup *stg, AVStream *st); AVProgram *av_new_program(AVFormatContext *s, int id); + +#define AVFMT_PROGCOPY_MATCH_BY_ID (1 << 0) ///< match streams using stream id +#define AVFMT_PROGCOPY_MATCH_BY_INDEX (1 << 1) ///< match streams using stream index +#define AVFMT_PROGCOPY_OVERWRITE (1 << 8) ///< overwrite pre-existing program having same ID + +/** + * Copy an AVProgram from one AVFormatContext to another. + * + * Streams in the destination context whose designated attribute match the attribute of + * the streams in the source AVProgram index are added to the stream index of the copied + * AVProgram. The attribute is designated using AVFMT_PROGCOPY_MATCH_ flags. + * + * If a new program has to be added, the function expects and requires any existing buffer + * holding the array of pointers to AVPrograms in the destination context to have its size + * be a power-of-two value. This should be the case if all earlier programs were created + * using av_new_program or this function. + * + * @param dst pointer to the target muxer context + * @param src pointer to the source muxer context + * @param progid ID of the program to be copied + * @param flags combination of flags which determine how streams are matched and + * whether pre-existing AVProgram in target is overwritten. + * If no match condition is set, streams will be matched by ids if + * all source stream ids are non-zero and unique, else by index. + * + * @return >= 0 in case of success, Error EEXIST if target already has program with same ID + * and overwrite flag isn't set, else a negative AVERROR code in case of other + * failures. + */ +int av_program_copy(AVFormatContext *dst, const AVFormatContext *src, int progid, int flags); + /** * @} */ diff --git a/libavformat/version.h b/libavformat/version.h index 14bf700274..eaf74946de 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 14 +#define LIBAVFORMAT_VERSION_MINOR 15 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
