avformat: add av_program_copy()
Helper to transfer programs from one muxing context to another.
This commit is contained in:
@@ -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().
|
||||
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -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, \
|
||||
|
||||
Reference in New Issue
Block a user