mirror of https://github.com/FFmpeg/FFmpeg.git
Compare commits
24 Commits
d31983dc8e
...
746650dfe5
| Author | SHA1 | Date |
|---|---|---|
|
|
746650dfe5 | |
|
|
a979c9b935 | |
|
|
5ff8395e78 | |
|
|
433d18a1d9 | |
|
|
dec3cc0138 | |
|
|
e7cf188bb6 | |
|
|
9dcd25b7cd | |
|
|
cce85642c9 | |
|
|
c751ad2c36 | |
|
|
99ec0752d7 | |
|
|
ba0dc3d49e | |
|
|
7b18beb477 | |
|
|
7ac1b410e1 | |
|
|
6879c8ee5d | |
|
|
0242cb36a5 | |
|
|
00c23bafb0 | |
|
|
82c495fd15 | |
|
|
0f105b96a3 | |
|
|
909af3a571 | |
|
|
d8ffec5bf9 | |
|
|
d03483bd26 | |
|
|
afd927e0ca | |
|
|
0d11c5c2f9 | |
|
|
3d12d5682b |
|
|
@ -9,6 +9,7 @@ version <next>:
|
||||||
- MPEG-H 3D Audio decoding via mpeghdec
|
- MPEG-H 3D Audio decoding via mpeghdec
|
||||||
- D3D12 H.264 encoder
|
- D3D12 H.264 encoder
|
||||||
- drawvg filter via libcairo
|
- drawvg filter via libcairo
|
||||||
|
- ffmpeg CLI tiled HEIF support
|
||||||
|
|
||||||
|
|
||||||
version 8.0:
|
version 8.0:
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,12 @@ The last version increases of all libraries were on 2025-03-28
|
||||||
|
|
||||||
API changes, most recent first:
|
API changes, most recent first:
|
||||||
|
|
||||||
|
2025-10-30 - xxxxxxxxxx - lavc 62.17.100 - packet.h
|
||||||
|
Add av_packet_side_data_from_frame() and av_packet_side_data_to_frame().
|
||||||
|
|
||||||
2025-10-xx - xxxxxxxxxx - lavu 60.16.100 - pixfmt.h
|
2025-10-xx - xxxxxxxxxx - lavu 60.16.100 - pixfmt.h
|
||||||
Add AVCOL_TRC_EXT_BASE and AVCOL_TRC_L_LOG.
|
Add AVCOL_TRC_EXT_BASE, AVCOL_TRC_V_LOG,
|
||||||
|
AVCOL_PRI_EXT_BASE and AVCOL_PRI_V_GAMUT.
|
||||||
|
|
||||||
2025-10-xx - xxxxxxxxxx - lavu 60.15.100 - pixfmt.h
|
2025-10-xx - xxxxxxxxxx - lavu 60.15.100 - pixfmt.h
|
||||||
Add AV_PIX_FMT_GRAY10MSB, AV_PIX_FMT_GRAY12MSB,
|
Add AV_PIX_FMT_GRAY10MSB, AV_PIX_FMT_GRAY12MSB,
|
||||||
|
|
|
||||||
|
|
@ -13056,7 +13056,9 @@ Draw vector graphics on top of video frames, by executing a script written in
|
||||||
a custom language called VGS (@emph{Vector Graphics Script}).
|
a custom language called VGS (@emph{Vector Graphics Script}).
|
||||||
|
|
||||||
The documentation for the language can be found in
|
The documentation for the language can be found in
|
||||||
@ref{,,drawvg - Language Reference,drawvg-reference}.
|
@ref{,,drawvg - Language Reference,drawvg-reference}. A version of this reference
|
||||||
|
with rendered examples can be found at the
|
||||||
|
@uref{https://ayosec.github.io/ffmpeg-drawvg/playground/docs/langref.html, author's site}.
|
||||||
|
|
||||||
Graphics are rendered using the @uref{https://cairographics.org/,cario 2D
|
Graphics are rendered using the @uref{https://cairographics.org/,cario 2D
|
||||||
graphics library}.
|
graphics library}.
|
||||||
|
|
|
||||||
|
|
@ -1350,6 +1350,77 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned stream_group_specifier_match(const StreamSpecifier *ss,
|
||||||
|
const AVFormatContext *s, const AVStreamGroup *stg,
|
||||||
|
void *logctx)
|
||||||
|
{
|
||||||
|
int start_stream_group = 0, nb_stream_groups;
|
||||||
|
int nb_matched = 0;
|
||||||
|
|
||||||
|
if (ss->idx >= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (ss->stream_list) {
|
||||||
|
case STREAM_LIST_STREAM_ID:
|
||||||
|
case STREAM_LIST_ALL:
|
||||||
|
case STREAM_LIST_PROGRAM:
|
||||||
|
return 0;
|
||||||
|
case STREAM_LIST_GROUP_ID:
|
||||||
|
// <n-th> stream with given ID makes no sense and should be impossible to request
|
||||||
|
av_assert0(ss->idx < 0);
|
||||||
|
// return early if we know for sure the stream does not match
|
||||||
|
if (stg->id != ss->list_id)
|
||||||
|
return 0;
|
||||||
|
start_stream_group = stg->index;
|
||||||
|
nb_stream_groups = stg->index + 1;
|
||||||
|
break;
|
||||||
|
case STREAM_LIST_GROUP_IDX:
|
||||||
|
start_stream_group = ss->list_id >= 0 ? 0 : stg->index;
|
||||||
|
nb_stream_groups = stg->index + 1;
|
||||||
|
break;
|
||||||
|
default: av_assert0(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = start_stream_group; i < nb_stream_groups; i++) {
|
||||||
|
const AVStreamGroup *candidate = s->stream_groups[i];
|
||||||
|
|
||||||
|
if (ss->meta_key) {
|
||||||
|
const AVDictionaryEntry *tag = av_dict_get(candidate->metadata,
|
||||||
|
ss->meta_key, NULL, 0);
|
||||||
|
|
||||||
|
if (!tag)
|
||||||
|
continue;
|
||||||
|
if (ss->meta_val && strcmp(tag->value, ss->meta_val))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ss->usable_only) {
|
||||||
|
switch (candidate->type) {
|
||||||
|
case AV_STREAM_GROUP_PARAMS_TILE_GRID: {
|
||||||
|
const AVStreamGroupTileGrid *tg = candidate->params.tile_grid;
|
||||||
|
if (!tg->coded_width || !tg->coded_height || !tg->nb_tiles ||
|
||||||
|
!tg->width || !tg->height || !tg->nb_tiles)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ss->disposition &&
|
||||||
|
(candidate->disposition & ss->disposition) != ss->disposition)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (stg == candidate)
|
||||||
|
return ss->list_id < 0 || ss->list_id == nb_matched;
|
||||||
|
|
||||||
|
nb_matched++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
|
int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id,
|
||||||
AVFormatContext *s, AVStream *st, const AVCodec *codec,
|
AVFormatContext *s, AVStream *st, const AVCodec *codec,
|
||||||
AVDictionary **dst, AVDictionary **opts_used)
|
AVDictionary **dst, AVDictionary **opts_used)
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,10 @@ unsigned stream_specifier_match(const StreamSpecifier *ss,
|
||||||
const AVFormatContext *s, const AVStream *st,
|
const AVFormatContext *s, const AVStream *st,
|
||||||
void *logctx);
|
void *logctx);
|
||||||
|
|
||||||
|
unsigned stream_group_specifier_match(const StreamSpecifier *ss,
|
||||||
|
const AVFormatContext *s, const AVStreamGroup *stg,
|
||||||
|
void *logctx);
|
||||||
|
|
||||||
void stream_specifier_uninit(StreamSpecifier *ss);
|
void stream_specifier_uninit(StreamSpecifier *ss);
|
||||||
|
|
||||||
typedef struct SpecifierOpt {
|
typedef struct SpecifierOpt {
|
||||||
|
|
|
||||||
|
|
@ -400,6 +400,7 @@ static void frame_data_free(void *opaque, uint8_t *data)
|
||||||
{
|
{
|
||||||
FrameData *fd = (FrameData *)data;
|
FrameData *fd = (FrameData *)data;
|
||||||
|
|
||||||
|
av_frame_side_data_free(&fd->side_data, &fd->nb_side_data);
|
||||||
avcodec_parameters_free(&fd->par_enc);
|
avcodec_parameters_free(&fd->par_enc);
|
||||||
|
|
||||||
av_free(data);
|
av_free(data);
|
||||||
|
|
@ -429,6 +430,8 @@ static int frame_data_ensure(AVBufferRef **dst, int writable)
|
||||||
|
|
||||||
memcpy(fd, fd_src, sizeof(*fd));
|
memcpy(fd, fd_src, sizeof(*fd));
|
||||||
fd->par_enc = NULL;
|
fd->par_enc = NULL;
|
||||||
|
fd->side_data = NULL;
|
||||||
|
fd->nb_side_data = 0;
|
||||||
|
|
||||||
if (fd_src->par_enc) {
|
if (fd_src->par_enc) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
@ -444,6 +447,16 @@ static int frame_data_ensure(AVBufferRef **dst, int writable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fd_src->nb_side_data) {
|
||||||
|
int ret = clone_side_data(&fd->side_data, &fd->nb_side_data,
|
||||||
|
fd_src->side_data, fd_src->nb_side_data, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
av_buffer_unref(dst);
|
||||||
|
av_buffer_unref(&src);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
av_buffer_unref(&src);
|
av_buffer_unref(&src);
|
||||||
} else {
|
} else {
|
||||||
fd->dec.frame_num = UINT64_MAX;
|
fd->dec.frame_num = UINT64_MAX;
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,7 @@ typedef struct StreamMap {
|
||||||
int disabled; /* 1 is this mapping is disabled by a negative map */
|
int disabled; /* 1 is this mapping is disabled by a negative map */
|
||||||
int file_index;
|
int file_index;
|
||||||
int stream_index;
|
int stream_index;
|
||||||
|
int group_index;
|
||||||
char *linklabel; /* name of an output link, for mapping lavfi outputs */
|
char *linklabel; /* name of an output link, for mapping lavfi outputs */
|
||||||
|
|
||||||
ViewSpecifier vs;
|
ViewSpecifier vs;
|
||||||
|
|
@ -299,6 +300,8 @@ enum OFilterFlags {
|
||||||
// produce 24-bit audio
|
// produce 24-bit audio
|
||||||
OFILTER_FLAG_AUDIO_24BIT = (1 << 1),
|
OFILTER_FLAG_AUDIO_24BIT = (1 << 1),
|
||||||
OFILTER_FLAG_AUTOSCALE = (1 << 2),
|
OFILTER_FLAG_AUTOSCALE = (1 << 2),
|
||||||
|
OFILTER_FLAG_AUTOROTATE = (1 << 3),
|
||||||
|
OFILTER_FLAG_CROP = (1 << 4),
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct OutputFilterOptions {
|
typedef struct OutputFilterOptions {
|
||||||
|
|
@ -332,6 +335,11 @@ typedef struct OutputFilterOptions {
|
||||||
enum AVColorRange color_range;
|
enum AVColorRange color_range;
|
||||||
enum AVAlphaMode alpha_mode;
|
enum AVAlphaMode alpha_mode;
|
||||||
|
|
||||||
|
unsigned crop_top;
|
||||||
|
unsigned crop_bottom;
|
||||||
|
unsigned crop_left;
|
||||||
|
unsigned crop_right;
|
||||||
|
|
||||||
enum VideoSyncMethod vsync_method;
|
enum VideoSyncMethod vsync_method;
|
||||||
AVRational frame_rate;
|
AVRational frame_rate;
|
||||||
AVRational max_frame_rate;
|
AVRational max_frame_rate;
|
||||||
|
|
@ -347,6 +355,9 @@ typedef struct OutputFilterOptions {
|
||||||
const enum AVColorRange *color_ranges;
|
const enum AVColorRange *color_ranges;
|
||||||
const enum AVAlphaMode *alpha_modes;
|
const enum AVAlphaMode *alpha_modes;
|
||||||
|
|
||||||
|
AVFrameSideData **side_data;
|
||||||
|
int nb_side_data;
|
||||||
|
|
||||||
// for simple filtergraphs only, view specifier passed
|
// for simple filtergraphs only, view specifier passed
|
||||||
// along to the decoder
|
// along to the decoder
|
||||||
const ViewSpecifier *vs;
|
const ViewSpecifier *vs;
|
||||||
|
|
@ -402,6 +413,11 @@ typedef struct FilterGraph {
|
||||||
OutputFilter **outputs;
|
OutputFilter **outputs;
|
||||||
int nb_outputs;
|
int nb_outputs;
|
||||||
|
|
||||||
|
// true when the filtergraph is created internally for
|
||||||
|
// purposes like stream group merging. Meant to be freed
|
||||||
|
// if unbound.
|
||||||
|
int is_internal;
|
||||||
|
|
||||||
const char *graph_desc;
|
const char *graph_desc;
|
||||||
struct AVBPrint graph_print_buf;
|
struct AVBPrint graph_print_buf;
|
||||||
} FilterGraph;
|
} FilterGraph;
|
||||||
|
|
@ -491,6 +507,18 @@ typedef struct InputStream {
|
||||||
int nb_filters;
|
int nb_filters;
|
||||||
} InputStream;
|
} InputStream;
|
||||||
|
|
||||||
|
typedef struct InputStreamGroup {
|
||||||
|
const AVClass *class;
|
||||||
|
|
||||||
|
/* parent source */
|
||||||
|
struct InputFile *file;
|
||||||
|
|
||||||
|
int index;
|
||||||
|
|
||||||
|
FilterGraph *fg;
|
||||||
|
AVStreamGroup *stg;
|
||||||
|
} InputStreamGroup;
|
||||||
|
|
||||||
typedef struct InputFile {
|
typedef struct InputFile {
|
||||||
const AVClass *class;
|
const AVClass *class;
|
||||||
|
|
||||||
|
|
@ -512,6 +540,10 @@ typedef struct InputFile {
|
||||||
* if new streams appear dynamically during demuxing */
|
* if new streams appear dynamically during demuxing */
|
||||||
InputStream **streams;
|
InputStream **streams;
|
||||||
int nb_streams;
|
int nb_streams;
|
||||||
|
|
||||||
|
/* stream groups that ffmpeg is aware of; */
|
||||||
|
InputStreamGroup **stream_groups;
|
||||||
|
int nb_stream_groups;
|
||||||
} InputFile;
|
} InputFile;
|
||||||
|
|
||||||
enum forced_keyframes_const {
|
enum forced_keyframes_const {
|
||||||
|
|
@ -698,6 +730,9 @@ typedef struct FrameData {
|
||||||
int64_t wallclock[LATENCY_PROBE_NB];
|
int64_t wallclock[LATENCY_PROBE_NB];
|
||||||
|
|
||||||
AVCodecParameters *par_enc;
|
AVCodecParameters *par_enc;
|
||||||
|
|
||||||
|
AVFrameSideData **side_data;
|
||||||
|
int nb_side_data;
|
||||||
} FrameData;
|
} FrameData;
|
||||||
|
|
||||||
extern InputFile **input_files;
|
extern InputFile **input_files;
|
||||||
|
|
@ -802,7 +837,8 @@ int ofilter_bind_enc(OutputFilter *ofilter,
|
||||||
* @param graph_desc Graph description; an av_malloc()ed string, filtergraph
|
* @param graph_desc Graph description; an av_malloc()ed string, filtergraph
|
||||||
* takes ownership of it.
|
* takes ownership of it.
|
||||||
*/
|
*/
|
||||||
int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch);
|
int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch,
|
||||||
|
const OutputFilterOptions *opts);
|
||||||
|
|
||||||
void fg_free(FilterGraph **pfg);
|
void fg_free(FilterGraph **pfg);
|
||||||
|
|
||||||
|
|
@ -929,6 +965,15 @@ void opt_match_per_stream_int64(void *logctx, const SpecifierOptList *sol,
|
||||||
void opt_match_per_stream_dbl(void *logctx, const SpecifierOptList *sol,
|
void opt_match_per_stream_dbl(void *logctx, const SpecifierOptList *sol,
|
||||||
AVFormatContext *fc, AVStream *st, double *out);
|
AVFormatContext *fc, AVStream *st, double *out);
|
||||||
|
|
||||||
|
void opt_match_per_stream_group_str(void *logctx, const SpecifierOptList *sol,
|
||||||
|
AVFormatContext *fc, AVStreamGroup *stg, const char **out);
|
||||||
|
void opt_match_per_stream_group_int(void *logctx, const SpecifierOptList *sol,
|
||||||
|
AVFormatContext *fc, AVStreamGroup *stg, int *out);
|
||||||
|
void opt_match_per_stream_group_int64(void *logctx, const SpecifierOptList *sol,
|
||||||
|
AVFormatContext *fc, AVStreamGroup *stg, int64_t *out);
|
||||||
|
void opt_match_per_stream_group_dbl(void *logctx, const SpecifierOptList *sol,
|
||||||
|
AVFormatContext *fc, AVStreamGroup *stg, double *out);
|
||||||
|
|
||||||
int view_specifier_parse(const char **pspec, ViewSpecifier *vs);
|
int view_specifier_parse(const char **pspec, ViewSpecifier *vs);
|
||||||
|
|
||||||
int muxer_thread(void *arg);
|
int muxer_thread(void *arg);
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,13 @@ typedef struct DemuxStream {
|
||||||
int64_t lag;
|
int64_t lag;
|
||||||
} DemuxStream;
|
} DemuxStream;
|
||||||
|
|
||||||
|
typedef struct DemuxStreamGroup {
|
||||||
|
InputStreamGroup istg;
|
||||||
|
|
||||||
|
// name used for logging
|
||||||
|
char log_name[32];
|
||||||
|
} DemuxStreamGroup;
|
||||||
|
|
||||||
typedef struct Demuxer {
|
typedef struct Demuxer {
|
||||||
InputFile f;
|
InputFile f;
|
||||||
|
|
||||||
|
|
@ -886,6 +893,16 @@ static void ist_free(InputStream **pist)
|
||||||
av_freep(pist);
|
av_freep(pist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void istg_free(InputStreamGroup **pistg)
|
||||||
|
{
|
||||||
|
InputStreamGroup *istg = *pistg;
|
||||||
|
|
||||||
|
if (!istg)
|
||||||
|
return;
|
||||||
|
|
||||||
|
av_freep(pistg);
|
||||||
|
}
|
||||||
|
|
||||||
void ifile_close(InputFile **pf)
|
void ifile_close(InputFile **pf)
|
||||||
{
|
{
|
||||||
InputFile *f = *pf;
|
InputFile *f = *pf;
|
||||||
|
|
@ -901,6 +918,10 @@ void ifile_close(InputFile **pf)
|
||||||
ist_free(&f->streams[i]);
|
ist_free(&f->streams[i]);
|
||||||
av_freep(&f->streams);
|
av_freep(&f->streams);
|
||||||
|
|
||||||
|
for (int i = 0; i < f->nb_stream_groups; i++)
|
||||||
|
istg_free(&f->stream_groups[i]);
|
||||||
|
av_freep(&f->stream_groups);
|
||||||
|
|
||||||
avformat_close_input(&f->ctx);
|
avformat_close_input(&f->ctx);
|
||||||
|
|
||||||
av_packet_free(&d->pkt_heartbeat);
|
av_packet_free(&d->pkt_heartbeat);
|
||||||
|
|
@ -1586,6 +1607,139 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st, AVDictiona
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *input_stream_group_item_name(void *obj)
|
||||||
|
{
|
||||||
|
const DemuxStreamGroup *dsg = obj;
|
||||||
|
|
||||||
|
return dsg->log_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const AVClass input_stream_group_class = {
|
||||||
|
.class_name = "InputStreamGroup",
|
||||||
|
.version = LIBAVUTIL_VERSION_INT,
|
||||||
|
.item_name = input_stream_group_item_name,
|
||||||
|
.category = AV_CLASS_CATEGORY_DEMUXER,
|
||||||
|
};
|
||||||
|
|
||||||
|
static DemuxStreamGroup *demux_stream_group_alloc(Demuxer *d, AVStreamGroup *stg)
|
||||||
|
{
|
||||||
|
InputFile *f = &d->f;
|
||||||
|
DemuxStreamGroup *dsg;
|
||||||
|
|
||||||
|
dsg = allocate_array_elem(&f->stream_groups, sizeof(*dsg), &f->nb_stream_groups);
|
||||||
|
if (!dsg)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dsg->istg.stg = stg;
|
||||||
|
dsg->istg.file = f;
|
||||||
|
dsg->istg.index = stg->index;
|
||||||
|
dsg->istg.class = &input_stream_group_class;
|
||||||
|
|
||||||
|
snprintf(dsg->log_name, sizeof(dsg->log_name), "istg#%d:%d/%s",
|
||||||
|
d->f.index, stg->index, avformat_stream_group_name(stg->type));
|
||||||
|
|
||||||
|
return dsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int istg_parse_tile_grid(const OptionsContext *o, Demuxer *d, InputStreamGroup *istg)
|
||||||
|
{
|
||||||
|
InputFile *f = &d->f;
|
||||||
|
AVFormatContext *ic = d->f.ctx;
|
||||||
|
AVStreamGroup *stg = istg->stg;
|
||||||
|
const AVStreamGroupTileGrid *tg = stg->params.tile_grid;
|
||||||
|
OutputFilterOptions opts;
|
||||||
|
AVBPrint bp;
|
||||||
|
char *graph_str;
|
||||||
|
int autorotate = 1;
|
||||||
|
const char *apply_cropping = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (tg->nb_tiles == 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memset(&opts, 0, sizeof(opts));
|
||||||
|
|
||||||
|
opt_match_per_stream_group_int(istg, &o->autorotate, ic, stg, &autorotate);
|
||||||
|
if (autorotate)
|
||||||
|
opts.flags |= OFILTER_FLAG_AUTOROTATE;
|
||||||
|
|
||||||
|
opts.flags |= OFILTER_FLAG_CROP;
|
||||||
|
opt_match_per_stream_group_str(istg, &o->apply_cropping, ic, stg, &apply_cropping);
|
||||||
|
if (apply_cropping) {
|
||||||
|
char *p;
|
||||||
|
int crop = strtol(apply_cropping, &p, 0);
|
||||||
|
if (*p)
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
if (!crop)
|
||||||
|
opts.flags &= ~OFILTER_FLAG_CROP;
|
||||||
|
}
|
||||||
|
|
||||||
|
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
|
||||||
|
for (int i = 0; i < tg->nb_tiles; i++)
|
||||||
|
av_bprintf(&bp, "[%d:g:%d:%d]", f->index, stg->index, tg->offsets[i].idx);
|
||||||
|
av_bprintf(&bp, "xstack=inputs=%d:layout=", tg->nb_tiles);
|
||||||
|
for (int i = 0; i < tg->nb_tiles - 1; i++)
|
||||||
|
av_bprintf(&bp, "%d_%d|", tg->offsets[i].horizontal,
|
||||||
|
tg->offsets[i].vertical);
|
||||||
|
av_bprintf(&bp, "%d_%d:fill=0x%02X%02X%02X@0x%02X", tg->offsets[tg->nb_tiles - 1].horizontal,
|
||||||
|
tg->offsets[tg->nb_tiles - 1].vertical,
|
||||||
|
tg->background[0], tg->background[1],
|
||||||
|
tg->background[2], tg->background[3]);
|
||||||
|
av_bprintf(&bp, "[%d:g:%d]", f->index, stg->index);
|
||||||
|
ret = av_bprint_finalize(&bp, &graph_str);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (tg->coded_width != tg->width || tg->coded_height != tg->height) {
|
||||||
|
opts.crop_top = tg->vertical_offset;
|
||||||
|
opts.crop_bottom = tg->coded_height - tg->height - tg->vertical_offset;
|
||||||
|
opts.crop_left = tg->horizontal_offset;
|
||||||
|
opts.crop_right = tg->coded_width - tg->width - tg->horizontal_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < tg->nb_coded_side_data; i++) {
|
||||||
|
const AVPacketSideData *sd = &tg->coded_side_data[i];
|
||||||
|
|
||||||
|
ret = av_packet_side_data_to_frame(&opts.side_data, &opts.nb_side_data, sd, 0);
|
||||||
|
if (ret < 0 && ret != AVERROR(EINVAL))
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fg_create(NULL, graph_str, d->sch, &opts);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
istg->fg = filtergraphs[nb_filtergraphs-1];
|
||||||
|
istg->fg->is_internal = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int istg_add(const OptionsContext *o, Demuxer *d, AVStreamGroup *stg)
|
||||||
|
{
|
||||||
|
DemuxStreamGroup *dsg;
|
||||||
|
InputStreamGroup *istg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dsg = demux_stream_group_alloc(d, stg);
|
||||||
|
if (!dsg)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
istg = &dsg->istg;
|
||||||
|
|
||||||
|
switch (stg->type) {
|
||||||
|
case AV_STREAM_GROUP_PARAMS_TILE_GRID:
|
||||||
|
ret = istg_parse_tile_grid(o, d, istg);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int dump_attachment(InputStream *ist, const char *filename)
|
static int dump_attachment(InputStream *ist, const char *filename)
|
||||||
{
|
{
|
||||||
AVStream *st = ist->st;
|
AVStream *st = ist->st;
|
||||||
|
|
@ -1954,6 +2108,13 @@ int ifile_open(const OptionsContext *o, const char *filename, Scheduler *sch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add all the stream groups from the given input file to the demuxer */
|
||||||
|
for (int i = 0; i < ic->nb_stream_groups; i++) {
|
||||||
|
ret = istg_add(o, d, ic->stream_groups[i]);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* dump the file content */
|
/* dump the file content */
|
||||||
av_dump_format(ic, f->index, filename, 0);
|
av_dump_format(ic, f->index, filename, 0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -205,19 +205,10 @@ int enc_open(void *opaque, const AVFrame *frame)
|
||||||
av_assert0(frame->opaque_ref);
|
av_assert0(frame->opaque_ref);
|
||||||
fd = (FrameData*)frame->opaque_ref->data;
|
fd = (FrameData*)frame->opaque_ref->data;
|
||||||
|
|
||||||
for (int i = 0; i < frame->nb_side_data; i++) {
|
ret = clone_side_data(&enc_ctx->decoded_side_data, &enc_ctx->nb_decoded_side_data,
|
||||||
const AVSideDataDescriptor *desc = av_frame_side_data_desc(frame->side_data[i]->type);
|
fd->side_data, fd->nb_side_data, AV_FRAME_SIDE_DATA_FLAG_UNIQUE);
|
||||||
|
if (ret < 0)
|
||||||
if (!(desc->props & AV_SIDE_DATA_PROP_GLOBAL))
|
return ret;
|
||||||
continue;
|
|
||||||
|
|
||||||
ret = av_frame_side_data_clone(&enc_ctx->decoded_side_data,
|
|
||||||
&enc_ctx->nb_decoded_side_data,
|
|
||||||
frame->side_data[i],
|
|
||||||
AV_FRAME_SIDE_DATA_FLAG_UNIQUE);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ist)
|
if (ist)
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,9 @@ typedef struct InputFilterPriv {
|
||||||
// used to hold submitted input
|
// used to hold submitted input
|
||||||
AVFrame *frame;
|
AVFrame *frame;
|
||||||
|
|
||||||
|
// For inputs bound to a filtergraph output
|
||||||
|
OutputFilter *ofilter_src;
|
||||||
|
|
||||||
// source data type: AVMEDIA_TYPE_SUBTITLE for sub2video,
|
// source data type: AVMEDIA_TYPE_SUBTITLE for sub2video,
|
||||||
// same as type otherwise
|
// same as type otherwise
|
||||||
enum AVMediaType type_src;
|
enum AVMediaType type_src;
|
||||||
|
|
@ -190,6 +193,8 @@ typedef struct OutputFilterPriv {
|
||||||
void *log_parent;
|
void *log_parent;
|
||||||
char log_name[32];
|
char log_name[32];
|
||||||
|
|
||||||
|
int needed;
|
||||||
|
|
||||||
/* desired output stream properties */
|
/* desired output stream properties */
|
||||||
int format;
|
int format;
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
@ -199,6 +204,11 @@ typedef struct OutputFilterPriv {
|
||||||
enum AVColorRange color_range;
|
enum AVColorRange color_range;
|
||||||
enum AVAlphaMode alpha_mode;
|
enum AVAlphaMode alpha_mode;
|
||||||
|
|
||||||
|
unsigned crop_top;
|
||||||
|
unsigned crop_bottom;
|
||||||
|
unsigned crop_left;
|
||||||
|
unsigned crop_right;
|
||||||
|
|
||||||
AVFrameSideData **side_data;
|
AVFrameSideData **side_data;
|
||||||
int nb_side_data;
|
int nb_side_data;
|
||||||
|
|
||||||
|
|
@ -223,6 +233,8 @@ typedef struct OutputFilterPriv {
|
||||||
const enum AVColorRange *color_ranges;
|
const enum AVColorRange *color_ranges;
|
||||||
const enum AVAlphaMode *alpha_modes;
|
const enum AVAlphaMode *alpha_modes;
|
||||||
|
|
||||||
|
int32_t displaymatrix[9];
|
||||||
|
|
||||||
AVRational enc_timebase;
|
AVRational enc_timebase;
|
||||||
int64_t trim_start_us;
|
int64_t trim_start_us;
|
||||||
int64_t trim_duration_us;
|
int64_t trim_duration_us;
|
||||||
|
|
@ -810,10 +822,10 @@ int ofilter_bind_enc(OutputFilter *ofilter, unsigned sched_idx_enc,
|
||||||
av_assert0(!opts->enc ||
|
av_assert0(!opts->enc ||
|
||||||
ofilter->type == opts->enc->type);
|
ofilter->type == opts->enc->type);
|
||||||
|
|
||||||
ofilter->bound = 1;
|
ofp->needed = ofilter->bound = 1;
|
||||||
av_freep(&ofilter->linklabel);
|
av_freep(&ofilter->linklabel);
|
||||||
|
|
||||||
ofp->flags = opts->flags;
|
ofp->flags |= opts->flags;
|
||||||
ofp->ts_offset = opts->ts_offset;
|
ofp->ts_offset = opts->ts_offset;
|
||||||
ofp->enc_timebase = opts->output_tb;
|
ofp->enc_timebase = opts->output_tb;
|
||||||
|
|
||||||
|
|
@ -921,13 +933,15 @@ static int ofilter_bind_ifilter(OutputFilter *ofilter, InputFilterPriv *ifp,
|
||||||
av_assert0(!ofilter->bound);
|
av_assert0(!ofilter->bound);
|
||||||
av_assert0(ofilter->type == ifp->ifilter.type);
|
av_assert0(ofilter->type == ifp->ifilter.type);
|
||||||
|
|
||||||
ofilter->bound = 1;
|
ofp->needed = ofilter->bound = 1;
|
||||||
av_freep(&ofilter->linklabel);
|
av_freep(&ofilter->linklabel);
|
||||||
|
|
||||||
ofilter->output_name = av_strdup(opts->name);
|
ofilter->output_name = av_strdup(opts->name);
|
||||||
if (!ofilter->output_name)
|
if (!ofilter->output_name)
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
|
|
||||||
|
ifp->ofilter_src = ofilter;
|
||||||
|
|
||||||
av_strlcatf(ofp->log_name, sizeof(ofp->log_name), "->%s", ofilter->output_name);
|
av_strlcatf(ofp->log_name, sizeof(ofp->log_name), "->%s", ofilter->output_name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1071,7 +1085,8 @@ static const AVClass fg_class = {
|
||||||
.category = AV_CLASS_CATEGORY_FILTER,
|
.category = AV_CLASS_CATEGORY_FILTER,
|
||||||
};
|
};
|
||||||
|
|
||||||
int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch)
|
int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch,
|
||||||
|
const OutputFilterOptions *opts)
|
||||||
{
|
{
|
||||||
FilterGraphPriv *fgp;
|
FilterGraphPriv *fgp;
|
||||||
FilterGraph *fg;
|
FilterGraph *fg;
|
||||||
|
|
@ -1168,11 +1183,13 @@ int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch)
|
||||||
const enum AVMediaType type = avfilter_pad_get_type(cur->filter_ctx->output_pads,
|
const enum AVMediaType type = avfilter_pad_get_type(cur->filter_ctx->output_pads,
|
||||||
cur->pad_idx);
|
cur->pad_idx);
|
||||||
OutputFilter *const ofilter = ofilter_alloc(fg, type);
|
OutputFilter *const ofilter = ofilter_alloc(fg, type);
|
||||||
|
OutputFilterPriv *ofp;
|
||||||
|
|
||||||
if (!ofilter) {
|
if (!ofilter) {
|
||||||
ret = AVERROR(ENOMEM);
|
ret = AVERROR(ENOMEM);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
ofp = ofp_from_ofilter(ofilter);
|
||||||
|
|
||||||
ofilter->linklabel = cur->name;
|
ofilter->linklabel = cur->name;
|
||||||
cur->name = NULL;
|
cur->name = NULL;
|
||||||
|
|
@ -1182,6 +1199,25 @@ int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch)
|
||||||
ret = AVERROR(ENOMEM);
|
ret = AVERROR(ENOMEM);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// opts should only be needed in this function to fill fields from filtergraphs
|
||||||
|
// whose output is meant to be treated as if it was stream, e.g. merged HEIF
|
||||||
|
// tile groups.
|
||||||
|
if (opts) {
|
||||||
|
ofp->flags = opts->flags;
|
||||||
|
ofp->side_data = opts->side_data;
|
||||||
|
ofp->nb_side_data = opts->nb_side_data;
|
||||||
|
|
||||||
|
ofp->crop_top = opts->crop_top;
|
||||||
|
ofp->crop_bottom = opts->crop_bottom;
|
||||||
|
ofp->crop_left = opts->crop_left;
|
||||||
|
ofp->crop_right = opts->crop_right;
|
||||||
|
|
||||||
|
const AVFrameSideData *sd = av_frame_side_data_get(ofp->side_data, ofp->nb_side_data,
|
||||||
|
AV_FRAME_DATA_DISPLAYMATRIX);
|
||||||
|
if (sd)
|
||||||
|
memcpy(ofp->displaymatrix, sd->data, sizeof(ofp->displaymatrix));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fg->nb_outputs) {
|
if (!fg->nb_outputs) {
|
||||||
|
|
@ -1218,7 +1254,7 @@ int fg_create_simple(FilterGraph **pfg,
|
||||||
FilterGraphPriv *fgp;
|
FilterGraphPriv *fgp;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = fg_create(pfg, graph_desc, sch);
|
ret = fg_create(pfg, graph_desc, sch, NULL);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
fg = *pfg;
|
fg = *pfg;
|
||||||
|
|
@ -1259,7 +1295,7 @@ int fg_create_simple(FilterGraph **pfg,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter)
|
static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter, int commit)
|
||||||
{
|
{
|
||||||
InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
|
InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
|
||||||
InputStream *ist = NULL;
|
InputStream *ist = NULL;
|
||||||
|
|
@ -1310,15 +1346,20 @@ static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter)
|
||||||
|
|
||||||
if (!ofilter->bound && ofilter->linklabel &&
|
if (!ofilter->bound && ofilter->linklabel &&
|
||||||
!strcmp(ofilter->linklabel, ifilter->linklabel)) {
|
!strcmp(ofilter->linklabel, ifilter->linklabel)) {
|
||||||
av_log(fg, AV_LOG_VERBOSE,
|
if (commit) {
|
||||||
"Binding input with label '%s' to filtergraph output %d:%d\n",
|
av_log(fg, AV_LOG_VERBOSE,
|
||||||
ifilter->linklabel, i, j);
|
"Binding input with label '%s' to filtergraph output %d:%d\n",
|
||||||
|
ifilter->linklabel, i, j);
|
||||||
|
|
||||||
ret = ifilter_bind_fg(ifp, fg_src, j);
|
ret = ifilter_bind_fg(ifp, fg_src, j);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
av_log(fg, AV_LOG_ERROR, "Error binding filtergraph input %s\n",
|
av_log(fg, AV_LOG_ERROR, "Error binding filtergraph input %s\n",
|
||||||
ifilter->linklabel);
|
ifilter->linklabel);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ofp_from_ofilter(ofilter)->needed = 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1366,10 +1407,38 @@ static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter)
|
||||||
}
|
}
|
||||||
ist = input_files[file_idx]->streams[st->index];
|
ist = input_files[file_idx]->streams[st->index];
|
||||||
|
|
||||||
av_log(fg, AV_LOG_VERBOSE,
|
if (commit)
|
||||||
"Binding input with label '%s' to input stream %d:%d\n",
|
av_log(fg, AV_LOG_VERBOSE,
|
||||||
ifilter->linklabel, ist->file->index, ist->index);
|
"Binding input with label '%s' to input stream %d:%d\n",
|
||||||
|
ifilter->linklabel, ist->file->index, ist->index);
|
||||||
} else {
|
} else {
|
||||||
|
// try finding an unbound filtergraph output
|
||||||
|
for (int i = 0; i < nb_filtergraphs; i++) {
|
||||||
|
FilterGraph *fg_src = filtergraphs[i];
|
||||||
|
|
||||||
|
if (fg == fg_src)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int j = 0; j < fg_src->nb_outputs; j++) {
|
||||||
|
OutputFilter *ofilter = fg_src->outputs[j];
|
||||||
|
|
||||||
|
if (!ofilter->bound) {
|
||||||
|
if (commit) {
|
||||||
|
av_log(fg, AV_LOG_VERBOSE,
|
||||||
|
"Binding unlabeled filtergraph input to filtergraph output %d:%d\n", i, j);
|
||||||
|
|
||||||
|
ret = ifilter_bind_fg(ifp, fg_src, j);
|
||||||
|
if (ret < 0) {
|
||||||
|
av_log(fg, AV_LOG_ERROR, "Error binding filtergraph input %d:%d\n", i, j);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ofp_from_ofilter(ofilter)->needed = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ist = ist_find_unused(type);
|
ist = ist_find_unused(type);
|
||||||
if (!ist) {
|
if (!ist) {
|
||||||
av_log(fg, AV_LOG_FATAL,
|
av_log(fg, AV_LOG_FATAL,
|
||||||
|
|
@ -1379,24 +1448,27 @@ static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter)
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
av_log(fg, AV_LOG_VERBOSE,
|
if (commit)
|
||||||
"Binding unlabeled input %d to input stream %d:%d\n",
|
av_log(fg, AV_LOG_VERBOSE,
|
||||||
ifilter->index, ist->file->index, ist->index);
|
"Binding unlabeled input %d to input stream %d:%d\n",
|
||||||
|
ifilter->index, ist->file->index, ist->index);
|
||||||
}
|
}
|
||||||
av_assert0(ist);
|
av_assert0(ist);
|
||||||
|
|
||||||
ret = ifilter_bind_ist(ifilter, ist, &vs);
|
if (commit) {
|
||||||
if (ret < 0) {
|
ret = ifilter_bind_ist(ifilter, ist, &vs);
|
||||||
av_log(fg, AV_LOG_ERROR,
|
if (ret < 0) {
|
||||||
"Error binding an input stream to complex filtergraph input %s.\n",
|
av_log(fg, AV_LOG_ERROR,
|
||||||
ifilter->name);
|
"Error binding an input stream to complex filtergraph input %s.\n",
|
||||||
return ret;
|
ifilter->name);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bind_inputs(FilterGraph *fg)
|
static int bind_inputs(FilterGraph *fg, int commit)
|
||||||
{
|
{
|
||||||
// bind filtergraph inputs to input streams or other filtergraphs
|
// bind filtergraph inputs to input streams or other filtergraphs
|
||||||
for (int i = 0; i < fg->nb_inputs; i++) {
|
for (int i = 0; i < fg->nb_inputs; i++) {
|
||||||
|
|
@ -1406,7 +1478,7 @@ static int bind_inputs(FilterGraph *fg)
|
||||||
if (ifp->bound)
|
if (ifp->bound)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = fg_complex_bind_input(fg, &ifp->ifilter);
|
ret = fg_complex_bind_input(fg, &ifp->ifilter, commit);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -1419,27 +1491,49 @@ int fg_finalise_bindings(void)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
for (int i = 0; i < nb_filtergraphs; i++) {
|
for (int i = 0; i < nb_filtergraphs; i++) {
|
||||||
ret = bind_inputs(filtergraphs[i]);
|
ret = bind_inputs(filtergraphs[i], 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that all outputs were bound
|
// check that all outputs were bound
|
||||||
for (int i = 0; i < nb_filtergraphs; i++) {
|
for (int i = nb_filtergraphs - 1; i >= 0; i--) {
|
||||||
FilterGraph *fg = filtergraphs[i];
|
FilterGraph *fg = filtergraphs[i];
|
||||||
|
FilterGraphPriv *fgp = fgp_from_fg(filtergraphs[i]);
|
||||||
|
|
||||||
for (int j = 0; j < fg->nb_outputs; j++) {
|
for (int j = 0; j < fg->nb_outputs; j++) {
|
||||||
OutputFilter *output = fg->outputs[j];
|
OutputFilter *output = fg->outputs[j];
|
||||||
if (!output->bound) {
|
if (!ofp_from_ofilter(output)->needed) {
|
||||||
av_log(fg, AV_LOG_FATAL,
|
if (!fg->is_internal) {
|
||||||
"Filter '%s' has output %d (%s) unconnected\n",
|
av_log(fg, AV_LOG_FATAL,
|
||||||
|
"Filter '%s' has output %d (%s) unconnected\n",
|
||||||
|
output->name, j,
|
||||||
|
output->linklabel ? (const char *)output->linklabel : "unlabeled");
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
av_log(fg, AV_LOG_DEBUG,
|
||||||
|
"Internal filter '%s' has output %d (%s) unconnected. Removing graph\n",
|
||||||
output->name, j,
|
output->name, j,
|
||||||
output->linklabel ? (const char *)output->linklabel : "unlabeled");
|
output->linklabel ? (const char *)output->linklabel : "unlabeled");
|
||||||
return AVERROR(EINVAL);
|
sch_remove_filtergraph(fgp->sch, fgp->sch_idx);
|
||||||
|
fg_free(&filtergraphs[i]);
|
||||||
|
nb_filtergraphs--;
|
||||||
|
if (nb_filtergraphs > 0)
|
||||||
|
memmove(&filtergraphs[i],
|
||||||
|
&filtergraphs[i + 1],
|
||||||
|
(nb_filtergraphs - i) * sizeof(*filtergraphs));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < nb_filtergraphs; i++) {
|
||||||
|
ret = bind_inputs(filtergraphs[i], 1);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1538,6 +1632,53 @@ static int configure_output_video_filter(FilterGraphPriv *fgp, AVFilterGraph *gr
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (ofp->flags & OFILTER_FLAG_CROP) {
|
||||||
|
char crop_buf[64];
|
||||||
|
snprintf(crop_buf, sizeof(crop_buf), "w=iw-%u-%u:h=ih-%u-%u:x=%u:y=%u",
|
||||||
|
ofp->crop_left, ofp->crop_right,
|
||||||
|
ofp->crop_top, ofp->crop_bottom,
|
||||||
|
ofp->crop_left, ofp->crop_top);
|
||||||
|
ret = insert_filter(&last_filter, &pad_idx, "crop", crop_buf);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ofp->flags & OFILTER_FLAG_AUTOROTATE) {
|
||||||
|
int32_t *displaymatrix = ofp->displaymatrix;
|
||||||
|
double theta;
|
||||||
|
|
||||||
|
theta = get_rotation(displaymatrix);
|
||||||
|
|
||||||
|
if (fabs(theta - 90) < 1.0) {
|
||||||
|
ret = insert_filter(&last_filter, &pad_idx, "transpose",
|
||||||
|
displaymatrix[3] > 0 ? "cclock_flip" : "clock");
|
||||||
|
} else if (fabs(theta - 180) < 1.0) {
|
||||||
|
if (displaymatrix[0] < 0) {
|
||||||
|
ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (displaymatrix[4] < 0) {
|
||||||
|
ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
|
||||||
|
}
|
||||||
|
} else if (fabs(theta - 270) < 1.0) {
|
||||||
|
ret = insert_filter(&last_filter, &pad_idx, "transpose",
|
||||||
|
displaymatrix[3] < 0 ? "clock_flip" : "cclock");
|
||||||
|
} else if (fabs(theta) > 1.0) {
|
||||||
|
char rotate_buf[64];
|
||||||
|
snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
|
||||||
|
ret = insert_filter(&last_filter, &pad_idx, "rotate", rotate_buf);
|
||||||
|
} else if (fabs(theta) < 1.0) {
|
||||||
|
if (displaymatrix && displaymatrix[4] < 0) {
|
||||||
|
ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
av_frame_side_data_remove(&ofp->side_data, &ofp->nb_side_data, AV_FRAME_DATA_DISPLAYMATRIX);
|
||||||
|
}
|
||||||
|
|
||||||
if ((ofp->width || ofp->height) && (ofp->flags & OFILTER_FLAG_AUTOSCALE)) {
|
if ((ofp->width || ofp->height) && (ofp->flags & OFILTER_FLAG_AUTOSCALE)) {
|
||||||
char args[255];
|
char args[255];
|
||||||
AVFilterContext *filter;
|
AVFilterContext *filter;
|
||||||
|
|
@ -2035,12 +2176,11 @@ static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt)
|
||||||
ret = av_buffersink_get_ch_layout(sink, &ofp->ch_layout);
|
ret = av_buffersink_get_ch_layout(sink, &ofp->ch_layout);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
av_frame_side_data_free(&ofp->side_data, &ofp->nb_side_data);
|
|
||||||
sd = av_buffersink_get_side_data(sink, &nb_sd);
|
sd = av_buffersink_get_side_data(sink, &nb_sd);
|
||||||
if (nb_sd)
|
if (nb_sd)
|
||||||
for (int j = 0; j < nb_sd; j++) {
|
for (int j = 0; j < nb_sd; j++) {
|
||||||
ret = av_frame_side_data_clone(&ofp->side_data, &ofp->nb_side_data,
|
ret = av_frame_side_data_clone(&ofp->side_data, &ofp->nb_side_data,
|
||||||
sd[j], 0);
|
sd[j], AV_FRAME_SIDE_DATA_FLAG_REPLACE);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_frame_side_data_free(&ofp->side_data, &ofp->nb_side_data);
|
av_frame_side_data_free(&ofp->side_data, &ofp->nb_side_data);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -2124,7 +2264,8 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr
|
||||||
for (int i = 0; i < frame->nb_side_data; i++) {
|
for (int i = 0; i < frame->nb_side_data; i++) {
|
||||||
const AVSideDataDescriptor *desc = av_frame_side_data_desc(frame->side_data[i]->type);
|
const AVSideDataDescriptor *desc = av_frame_side_data_desc(frame->side_data[i]->type);
|
||||||
|
|
||||||
if (!(desc->props & AV_SIDE_DATA_PROP_GLOBAL))
|
if (!(desc->props & AV_SIDE_DATA_PROP_GLOBAL) ||
|
||||||
|
frame->side_data[i]->type == AV_FRAME_DATA_DISPLAYMATRIX)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = av_frame_side_data_clone(&ifp->side_data,
|
ret = av_frame_side_data_clone(&ifp->side_data,
|
||||||
|
|
@ -2155,6 +2296,27 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ifilter_parameters_from_ofilter(InputFilter *ifilter, OutputFilter *ofilter)
|
||||||
|
{
|
||||||
|
const OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
|
||||||
|
InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
|
||||||
|
|
||||||
|
if (!ifp->opts.framerate.num) {
|
||||||
|
ifp->opts.framerate = ofp->fps.framerate;
|
||||||
|
if (ifp->opts.framerate.num > 0 && ifp->opts.framerate.den > 0)
|
||||||
|
ifp->opts.flags |= IFILTER_FLAG_CFR;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ofp->nb_side_data; i++) {
|
||||||
|
int ret = av_frame_side_data_clone(&ifp->side_data, &ifp->nb_side_data,
|
||||||
|
ofp->side_data[i], AV_FRAME_SIDE_DATA_FLAG_REPLACE);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int filtergraph_is_simple(const FilterGraph *fg)
|
int filtergraph_is_simple(const FilterGraph *fg)
|
||||||
{
|
{
|
||||||
const FilterGraphPriv *fgp = cfgp_from_cfg(fg);
|
const FilterGraphPriv *fgp = cfgp_from_cfg(fg);
|
||||||
|
|
@ -2476,16 +2638,17 @@ static int close_output(OutputFilterPriv *ofp, FilterGraphThread *fgt)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
av_frame_side_data_free(&frame->side_data, &frame->nb_side_data);
|
|
||||||
ret = clone_side_data(&frame->side_data, &frame->nb_side_data,
|
|
||||||
ofp->side_data, ofp->nb_side_data, 0);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
fd = frame_data(frame);
|
fd = frame_data(frame);
|
||||||
if (!fd)
|
if (!fd)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
av_frame_side_data_free(&fd->side_data, &fd->nb_side_data);
|
||||||
|
ret = clone_side_data(&fd->side_data, &fd->nb_side_data,
|
||||||
|
ofp->side_data, ofp->nb_side_data, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
fd->frame_rate_filter = ofp->fps.framerate;
|
fd->frame_rate_filter = ofp->fps.framerate;
|
||||||
|
|
||||||
av_assert0(!frame->buf[0]);
|
av_assert0(!frame->buf[0]);
|
||||||
|
|
@ -2640,6 +2803,14 @@ static int fg_output_step(OutputFilterPriv *ofp, FilterGraphThread *fgt,
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
av_frame_side_data_free(&fd->side_data, &fd->nb_side_data);
|
||||||
|
if (!fgt->got_frame) {
|
||||||
|
ret = clone_side_data(&fd->side_data, &fd->nb_side_data,
|
||||||
|
ofp->side_data, ofp->nb_side_data, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
fd->wallclock[LATENCY_PROBE_FILTER_POST] = av_gettime_relative();
|
fd->wallclock[LATENCY_PROBE_FILTER_POST] = av_gettime_relative();
|
||||||
|
|
||||||
// only use bits_per_raw_sample passed through from the decoder
|
// only use bits_per_raw_sample passed through from the decoder
|
||||||
|
|
@ -2935,6 +3106,14 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
|
||||||
ret = ifilter_parameters_from_frame(ifilter, frame);
|
ret = ifilter_parameters_from_frame(ifilter, frame);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* Inputs bound to a filtergraph output will have some fields unset.
|
||||||
|
* Handle them here */
|
||||||
|
if (ifp->ofilter_src) {
|
||||||
|
ret = ifilter_parameters_from_ofilter(ifilter, ifp->ofilter_src);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (re)init the graph if possible, otherwise buffer the frame and return */
|
/* (re)init the graph if possible, otherwise buffer the frame and return */
|
||||||
|
|
|
||||||
|
|
@ -1598,6 +1598,7 @@ fail:
|
||||||
static int map_auto_video(Muxer *mux, const OptionsContext *o)
|
static int map_auto_video(Muxer *mux, const OptionsContext *o)
|
||||||
{
|
{
|
||||||
AVFormatContext *oc = mux->fc;
|
AVFormatContext *oc = mux->fc;
|
||||||
|
InputStreamGroup *best_istg = NULL;
|
||||||
InputStream *best_ist = NULL;
|
InputStream *best_ist = NULL;
|
||||||
int64_t best_score = 0;
|
int64_t best_score = 0;
|
||||||
int qcr;
|
int qcr;
|
||||||
|
|
@ -1609,8 +1610,41 @@ static int map_auto_video(Muxer *mux, const OptionsContext *o)
|
||||||
qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0);
|
qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0);
|
||||||
for (int j = 0; j < nb_input_files; j++) {
|
for (int j = 0; j < nb_input_files; j++) {
|
||||||
InputFile *ifile = input_files[j];
|
InputFile *ifile = input_files[j];
|
||||||
|
InputStreamGroup *file_best_istg = NULL;
|
||||||
InputStream *file_best_ist = NULL;
|
InputStream *file_best_ist = NULL;
|
||||||
int64_t file_best_score = 0;
|
int64_t file_best_score = 0;
|
||||||
|
for (int i = 0; i < ifile->nb_stream_groups; i++) {
|
||||||
|
InputStreamGroup *istg = ifile->stream_groups[i];
|
||||||
|
int64_t score = 0;
|
||||||
|
|
||||||
|
if (!istg->fg)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int j = 0; j < istg->stg->nb_streams; j++) {
|
||||||
|
AVStream *st = istg->stg->streams[j];
|
||||||
|
|
||||||
|
if (st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) {
|
||||||
|
score = 100000000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (istg->stg->type) {
|
||||||
|
case AV_STREAM_GROUP_PARAMS_TILE_GRID: {
|
||||||
|
const AVStreamGroupTileGrid *tg = istg->stg->params.tile_grid;
|
||||||
|
score += tg->width * (int64_t)tg->height
|
||||||
|
+ 5000000*!!(istg->stg->disposition & AV_DISPOSITION_DEFAULT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (score > file_best_score) {
|
||||||
|
file_best_score = score;
|
||||||
|
file_best_istg = istg;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (int i = 0; i < ifile->nb_streams; i++) {
|
for (int i = 0; i < ifile->nb_streams; i++) {
|
||||||
InputStream *ist = ifile->streams[i];
|
InputStream *ist = ifile->streams[i];
|
||||||
int64_t score;
|
int64_t score;
|
||||||
|
|
@ -1630,6 +1664,15 @@ static int map_auto_video(Muxer *mux, const OptionsContext *o)
|
||||||
continue;
|
continue;
|
||||||
file_best_score = score;
|
file_best_score = score;
|
||||||
file_best_ist = ist;
|
file_best_ist = ist;
|
||||||
|
file_best_istg = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (file_best_istg) {
|
||||||
|
file_best_score -= 5000000*!!(file_best_istg->stg->disposition & AV_DISPOSITION_DEFAULT);
|
||||||
|
if (file_best_score > best_score) {
|
||||||
|
best_score = file_best_score;
|
||||||
|
best_istg = file_best_istg;
|
||||||
|
best_ist = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (file_best_ist) {
|
if (file_best_ist) {
|
||||||
|
|
@ -1639,9 +1682,19 @@ static int map_auto_video(Muxer *mux, const OptionsContext *o)
|
||||||
if (file_best_score > best_score) {
|
if (file_best_score > best_score) {
|
||||||
best_score = file_best_score;
|
best_score = file_best_score;
|
||||||
best_ist = file_best_ist;
|
best_ist = file_best_ist;
|
||||||
|
best_istg = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (best_istg) {
|
||||||
|
FilterGraph *fg = best_istg->fg;
|
||||||
|
OutputFilter *ofilter = fg->outputs[0];
|
||||||
|
|
||||||
|
av_assert0(fg->nb_outputs == 1);
|
||||||
|
av_log(mux, AV_LOG_VERBOSE, "Creating output stream from stream group derived complex filtergraph %d.\n", fg->index);
|
||||||
|
|
||||||
|
return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, NULL, ofilter, NULL, NULL);
|
||||||
|
}
|
||||||
if (best_ist)
|
if (best_ist)
|
||||||
return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist, NULL, NULL, NULL);
|
return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -242,6 +242,70 @@ OPT_MATCH_PER_STREAM(int, int, OPT_TYPE_INT, i);
|
||||||
OPT_MATCH_PER_STREAM(int64, int64_t, OPT_TYPE_INT64, i64);
|
OPT_MATCH_PER_STREAM(int64, int64_t, OPT_TYPE_INT64, i64);
|
||||||
OPT_MATCH_PER_STREAM(dbl, double, OPT_TYPE_DOUBLE, dbl);
|
OPT_MATCH_PER_STREAM(dbl, double, OPT_TYPE_DOUBLE, dbl);
|
||||||
|
|
||||||
|
static unsigned opt_match_per_stream_group(void *logctx, enum OptionType type,
|
||||||
|
const SpecifierOptList *sol,
|
||||||
|
AVFormatContext *fc, AVStreamGroup *stg)
|
||||||
|
{
|
||||||
|
int matches = 0, match_idx = -1;
|
||||||
|
|
||||||
|
av_assert0((type == sol->type) || !sol->nb_opt);
|
||||||
|
|
||||||
|
for (int i = 0; i < sol->nb_opt; i++) {
|
||||||
|
const StreamSpecifier *ss = &sol->opt[i].stream_spec;
|
||||||
|
|
||||||
|
if (stream_group_specifier_match(ss, fc, stg, logctx)) {
|
||||||
|
match_idx = i;
|
||||||
|
matches++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matches > 1 && sol->opt_canon) {
|
||||||
|
const SpecifierOpt *so = &sol->opt[match_idx];
|
||||||
|
const char *spec = so->specifier && so->specifier[0] ? so->specifier : "";
|
||||||
|
|
||||||
|
char namestr[128] = "";
|
||||||
|
char optval_buf[32];
|
||||||
|
const char *optval = optval_buf;
|
||||||
|
|
||||||
|
snprintf(namestr, sizeof(namestr), "-%s", sol->opt_canon->name);
|
||||||
|
if (sol->opt_canon->flags & OPT_HAS_ALT) {
|
||||||
|
const char * const *names_alt = sol->opt_canon->u1.names_alt;
|
||||||
|
for (int i = 0; names_alt[i]; i++)
|
||||||
|
av_strlcatf(namestr, sizeof(namestr), "/-%s", names_alt[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (sol->type) {
|
||||||
|
case OPT_TYPE_STRING: optval = so->u.str; break;
|
||||||
|
case OPT_TYPE_INT: snprintf(optval_buf, sizeof(optval_buf), "%d", so->u.i); break;
|
||||||
|
case OPT_TYPE_INT64: snprintf(optval_buf, sizeof(optval_buf), "%"PRId64, so->u.i64); break;
|
||||||
|
case OPT_TYPE_FLOAT: snprintf(optval_buf, sizeof(optval_buf), "%f", so->u.f); break;
|
||||||
|
case OPT_TYPE_DOUBLE: snprintf(optval_buf, sizeof(optval_buf), "%f", so->u.dbl); break;
|
||||||
|
default: av_assert0(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
av_log(logctx, AV_LOG_WARNING, "Multiple %s options specified for "
|
||||||
|
"stream group %d, only the last option '-%s%s%s %s' will be used.\n",
|
||||||
|
namestr, stg->index, sol->opt_canon->name, spec[0] ? ":" : "",
|
||||||
|
spec, optval);
|
||||||
|
}
|
||||||
|
|
||||||
|
return match_idx + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OPT_MATCH_PER_STREAM_GROUP(name, type, opt_type, m) \
|
||||||
|
void opt_match_per_stream_group_ ## name(void *logctx, const SpecifierOptList *sol, \
|
||||||
|
AVFormatContext *fc, AVStreamGroup *stg, type *out) \
|
||||||
|
{ \
|
||||||
|
unsigned ret = opt_match_per_stream_group(logctx, opt_type, sol, fc, stg); \
|
||||||
|
if (ret > 0) \
|
||||||
|
*out = sol->opt[ret - 1].u.m; \
|
||||||
|
}
|
||||||
|
|
||||||
|
OPT_MATCH_PER_STREAM_GROUP(str, const char *, OPT_TYPE_STRING, str);
|
||||||
|
OPT_MATCH_PER_STREAM_GROUP(int, int, OPT_TYPE_INT, i);
|
||||||
|
OPT_MATCH_PER_STREAM_GROUP(int64, int64_t, OPT_TYPE_INT64, i64);
|
||||||
|
OPT_MATCH_PER_STREAM_GROUP(dbl, double, OPT_TYPE_DOUBLE, dbl);
|
||||||
|
|
||||||
int view_specifier_parse(const char **pspec, ViewSpecifier *vs)
|
int view_specifier_parse(const char **pspec, ViewSpecifier *vs)
|
||||||
{
|
{
|
||||||
const char *spec = *pspec;
|
const char *spec = *pspec;
|
||||||
|
|
@ -504,8 +568,10 @@ static int opt_map(void *optctx, const char *opt, const char *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg[0] == '[') {
|
if (arg[0] == '[') {
|
||||||
|
ViewSpecifier vs;
|
||||||
/* this mapping refers to lavfi output */
|
/* this mapping refers to lavfi output */
|
||||||
const char *c = arg + 1;
|
const char *c = arg + 1;
|
||||||
|
char *endptr;
|
||||||
|
|
||||||
ret = GROW_ARRAY(o->stream_maps, o->nb_stream_maps);
|
ret = GROW_ARRAY(o->stream_maps, o->nb_stream_maps);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
@ -518,6 +584,27 @@ static int opt_map(void *optctx, const char *opt, const char *arg)
|
||||||
ret = AVERROR(EINVAL);
|
ret = AVERROR(EINVAL);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arg++;
|
||||||
|
|
||||||
|
m->group_index = -1;
|
||||||
|
file_idx = strtol(arg, &endptr, 0);
|
||||||
|
if (file_idx >= nb_input_files || file_idx < 0)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
arg = endptr;
|
||||||
|
ret = stream_specifier_parse(&ss, *arg == ':' ? arg + 1 : arg, 1, NULL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
arg = ss.remainder ? ss.remainder : "";
|
||||||
|
ret = view_specifier_parse(&arg, &vs);
|
||||||
|
if (ret < 0 || (*arg && strcmp(arg, "]")))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
m->file_index = file_idx;
|
||||||
|
m->stream_index = ss.idx;
|
||||||
|
m->group_index = ss.stream_list == STREAM_LIST_GROUP_IDX ? ss.list_id : -1;
|
||||||
} else {
|
} else {
|
||||||
ViewSpecifier vs;
|
ViewSpecifier vs;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
@ -583,6 +670,7 @@ static int opt_map(void *optctx, const char *opt, const char *arg)
|
||||||
|
|
||||||
m->file_index = file_idx;
|
m->file_index = file_idx;
|
||||||
m->stream_index = i;
|
m->stream_index = i;
|
||||||
|
m->group_index = ss.stream_list == STREAM_LIST_GROUP_IDX ? ss.list_id : -1;
|
||||||
m->vs = vs;
|
m->vs = vs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -602,6 +690,7 @@ static int opt_map(void *optctx, const char *opt, const char *arg)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
end:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
fail:
|
fail:
|
||||||
stream_specifier_uninit(&ss);
|
stream_specifier_uninit(&ss);
|
||||||
|
|
@ -1407,7 +1496,7 @@ int ffmpeg_parse_options(int argc, char **argv, Scheduler *sch)
|
||||||
|
|
||||||
/* create complex filtergraphs */
|
/* create complex filtergraphs */
|
||||||
for (int i = 0; i < go.nb_filtergraphs; i++) {
|
for (int i = 0; i < go.nb_filtergraphs; i++) {
|
||||||
ret = fg_create(NULL, go.filtergraphs[i], sch);
|
ret = fg_create(NULL, go.filtergraphs[i], sch, NULL);
|
||||||
go.filtergraphs[i] = NULL;
|
go.filtergraphs[i] = NULL;
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
|
|
@ -405,6 +405,9 @@ static int task_start(SchTask *task)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!task->parent)
|
||||||
|
return 0;
|
||||||
|
|
||||||
av_log(task->func_arg, AV_LOG_VERBOSE, "Starting thread...\n");
|
av_log(task->func_arg, AV_LOG_VERBOSE, "Starting thread...\n");
|
||||||
|
|
||||||
av_assert0(!task->thread_running);
|
av_assert0(!task->thread_running);
|
||||||
|
|
@ -454,6 +457,23 @@ static int64_t trailing_dts(const Scheduler *sch, int count_finished)
|
||||||
return min_dts == INT64_MAX ? AV_NOPTS_VALUE : min_dts;
|
return min_dts == INT64_MAX ? AV_NOPTS_VALUE : min_dts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sch_remove_filtergraph(Scheduler *sch, int idx)
|
||||||
|
{
|
||||||
|
SchFilterGraph *fg = &sch->filters[idx];
|
||||||
|
|
||||||
|
av_assert0(!fg->task.thread_running);
|
||||||
|
memset(&fg->task, 0, sizeof(fg->task));
|
||||||
|
|
||||||
|
tq_free(&fg->queue);
|
||||||
|
|
||||||
|
av_freep(&fg->inputs);
|
||||||
|
fg->nb_inputs = 0;
|
||||||
|
av_freep(&fg->outputs);
|
||||||
|
fg->nb_outputs = 0;
|
||||||
|
|
||||||
|
fg->task_exited = 1;
|
||||||
|
}
|
||||||
|
|
||||||
void sch_free(Scheduler **psch)
|
void sch_free(Scheduler **psch)
|
||||||
{
|
{
|
||||||
Scheduler *sch = *psch;
|
Scheduler *sch = *psch;
|
||||||
|
|
@ -2630,6 +2650,9 @@ static int task_stop(Scheduler *sch, SchTask *task)
|
||||||
int ret;
|
int ret;
|
||||||
void *thread_ret;
|
void *thread_ret;
|
||||||
|
|
||||||
|
if (!task->parent)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!task->thread_running)
|
if (!task->thread_running)
|
||||||
return task_cleanup(sch, task->node);
|
return task_cleanup(sch, task->node);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,8 @@ int sch_add_dec_output(Scheduler *sch, unsigned dec_idx);
|
||||||
int sch_add_filtergraph(Scheduler *sch, unsigned nb_inputs, unsigned nb_outputs,
|
int sch_add_filtergraph(Scheduler *sch, unsigned nb_inputs, unsigned nb_outputs,
|
||||||
SchThreadFunc func, void *ctx);
|
SchThreadFunc func, void *ctx);
|
||||||
|
|
||||||
|
void sch_remove_filtergraph(Scheduler *sch, int idx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a muxer to the scheduler.
|
* Add a muxer to the scheduler.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -815,3 +815,53 @@ int avcodec_get_supported_config(const AVCodecContext *avctx, const AVCodec *cod
|
||||||
return ff_default_get_supported_config(avctx, codec, config, flags, out, out_num);
|
return ff_default_get_supported_config(avctx, codec, config, flags, out, out_num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int av_packet_side_data_from_frame(AVPacketSideData **psd, int *pnb_sd,
|
||||||
|
const AVFrameSideData *src, unsigned int flags)
|
||||||
|
{
|
||||||
|
AVPacketSideData *sd = NULL;
|
||||||
|
|
||||||
|
for (unsigned j = 0; ff_sd_global_map[j].packet < AV_PKT_DATA_NB; j++) {
|
||||||
|
if (ff_sd_global_map[j].frame != src->type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sd = av_packet_side_data_new(psd, pnb_sd, ff_sd_global_map[j].packet,
|
||||||
|
src->size, 0);
|
||||||
|
|
||||||
|
if (!sd)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
memcpy(sd->data, src->data, src->size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sd)
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int av_packet_side_data_to_frame(AVFrameSideData ***psd, int *pnb_sd,
|
||||||
|
const AVPacketSideData *src, unsigned int flags)
|
||||||
|
{
|
||||||
|
AVFrameSideData *sd = NULL;
|
||||||
|
|
||||||
|
for (unsigned j = 0; ff_sd_global_map[j].packet < AV_PKT_DATA_NB; j++) {
|
||||||
|
if (ff_sd_global_map[j].packet != src->type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sd = av_frame_side_data_new(psd, pnb_sd, ff_sd_global_map[j].frame,
|
||||||
|
src->size, flags);
|
||||||
|
|
||||||
|
if (!sd)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
memcpy(sd->data, src->data, src->size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sd)
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ typedef struct HFParam {
|
||||||
* Optimized fixed codebook excitation parameters
|
* Optimized fixed codebook excitation parameters
|
||||||
*/
|
*/
|
||||||
typedef struct FCBParam {
|
typedef struct FCBParam {
|
||||||
int min_err;
|
int64_t min_err;
|
||||||
int amp_index;
|
int amp_index;
|
||||||
int grid_index;
|
int grid_index;
|
||||||
int dirac_train;
|
int dirac_train;
|
||||||
|
|
|
||||||
|
|
@ -1013,7 +1013,7 @@ static void fcb_search(G723_1_ChannelContext *p, int16_t *impulse_resp,
|
||||||
int pulse_cnt = pulses[index];
|
int pulse_cnt = pulses[index];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
optim.min_err = 1 << 30;
|
optim.min_err = 1LL << 31;
|
||||||
get_fcb_param(&optim, impulse_resp, buf, pulse_cnt, SUBFRAME_LEN);
|
get_fcb_param(&optim, impulse_resp, buf, pulse_cnt, SUBFRAME_LEN);
|
||||||
|
|
||||||
if (p->pitch_lag[index >> 1] < SUBFRAME_LEN - 2) {
|
if (p->pitch_lag[index >> 1] < SUBFRAME_LEN - 2) {
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,6 @@ int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx,
|
||||||
static int decode_profile_tier_level(GetBitContext *gb, AVCodecContext *avctx,
|
static int decode_profile_tier_level(GetBitContext *gb, AVCodecContext *avctx,
|
||||||
PTLCommon *ptl)
|
PTLCommon *ptl)
|
||||||
{
|
{
|
||||||
const char *profile_name = NULL;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (get_bits_left(gb) < 2+1+5 + 32 + 4 + 43 + 1)
|
if (get_bits_left(gb) < 2+1+5 + 32 + 4 + 43 + 1)
|
||||||
|
|
@ -249,14 +248,15 @@ static int decode_profile_tier_level(GetBitContext *gb, AVCodecContext *avctx,
|
||||||
ptl->profile_idc = get_bits(gb, 5);
|
ptl->profile_idc = get_bits(gb, 5);
|
||||||
|
|
||||||
#if !CONFIG_SMALL
|
#if !CONFIG_SMALL
|
||||||
|
const char *profile_name = NULL;
|
||||||
for (int i = 0; ff_hevc_profiles[i].profile != AV_PROFILE_UNKNOWN; i++)
|
for (int i = 0; ff_hevc_profiles[i].profile != AV_PROFILE_UNKNOWN; i++)
|
||||||
if (ff_hevc_profiles[i].profile == ptl->profile_idc) {
|
if (ff_hevc_profiles[i].profile == ptl->profile_idc) {
|
||||||
profile_name = ff_hevc_profiles[i].name;
|
profile_name = ff_hevc_profiles[i].name;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
av_log(avctx, profile_name ? AV_LOG_DEBUG : AV_LOG_WARNING,
|
av_log(avctx, profile_name ? AV_LOG_DEBUG : AV_LOG_WARNING,
|
||||||
"%s profile bitstream\n", profile_name ? profile_name : "Unknown");
|
"%s profile bitstream\n", profile_name ? profile_name : "Unknown");
|
||||||
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
ptl->profile_compatibility_flag[i] = get_bits1(gb);
|
ptl->profile_compatibility_flag[i] = get_bits1(gb);
|
||||||
|
|
|
||||||
|
|
@ -489,6 +489,36 @@ void av_packet_side_data_remove(AVPacketSideData *sd, int *nb_sd,
|
||||||
*/
|
*/
|
||||||
void av_packet_side_data_free(AVPacketSideData **sd, int *nb_sd);
|
void av_packet_side_data_free(AVPacketSideData **sd, int *nb_sd);
|
||||||
|
|
||||||
|
struct AVFrameSideData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new packet side data entry to an array based on existing frame
|
||||||
|
* side data, if a matching type exists for packet side data.
|
||||||
|
*
|
||||||
|
* @param flags Currently unused. Must be 0.
|
||||||
|
* @retval >= 0 Success
|
||||||
|
* @retval AVERROR(EINVAL) The frame side data type does not have a matching
|
||||||
|
* packet side data type.
|
||||||
|
* @retval AVERROR(ENOMEM) Failed to add a side data entry to the array, or
|
||||||
|
* similar.
|
||||||
|
*/
|
||||||
|
int av_packet_side_data_from_frame(AVPacketSideData **sd, int *nb_sd,
|
||||||
|
const struct AVFrameSideData *src, unsigned int flags);
|
||||||
|
/**
|
||||||
|
* Add a new frame side data entry to an array based on existing packet
|
||||||
|
* side data, if a matching type exists for frame side data.
|
||||||
|
*
|
||||||
|
* @param flags Some combination of AV_FRAME_SIDE_DATA_FLAG_* flags,
|
||||||
|
* or 0.
|
||||||
|
* @retval >= 0 Success
|
||||||
|
* @retval AVERROR(EINVAL) The packet side data type does not have a matching
|
||||||
|
* frame side data type.
|
||||||
|
* @retval AVERROR(ENOMEM) Failed to add a side data entry to the array, or
|
||||||
|
* similar.
|
||||||
|
*/
|
||||||
|
int av_packet_side_data_to_frame(struct AVFrameSideData ***sd, int *nb_sd,
|
||||||
|
const AVPacketSideData *src, unsigned int flags);
|
||||||
|
|
||||||
const char *av_packet_side_data_name(enum AVPacketSideDataType type);
|
const char *av_packet_side_data_name(enum AVPacketSideDataType type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -334,6 +334,9 @@ static int decode_frame(AVCodecContext *avctx,
|
||||||
DECLARE_ALIGNED(32, uint8_t, qmat)[64];
|
DECLARE_ALIGNED(32, uint8_t, qmat)[64];
|
||||||
memset(qmat, 1, 64);
|
memset(qmat, 1, 64);
|
||||||
|
|
||||||
|
if (avctx->skip_frame >= AVDISCARD_ALL)
|
||||||
|
return avpkt->size;
|
||||||
|
|
||||||
switch (avctx->codec_tag) {
|
switch (avctx->codec_tag) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,8 @@ typedef int (*rv40_loop_filter_strength_func)(uint8_t *src, ptrdiff_t stride,
|
||||||
int *p1, int *q1);
|
int *p1, int *q1);
|
||||||
|
|
||||||
typedef struct RV34DSPContext {
|
typedef struct RV34DSPContext {
|
||||||
qpel_mc_func put_pixels_tab[4][16];
|
qpel_mc_func put_pixels_tab[2][16];
|
||||||
qpel_mc_func avg_pixels_tab[4][16];
|
qpel_mc_func avg_pixels_tab[2][16];
|
||||||
h264_chroma_mc_func put_chroma_pixels_tab[3];
|
h264_chroma_mc_func put_chroma_pixels_tab[3];
|
||||||
h264_chroma_mc_func avg_chroma_pixels_tab[3];
|
h264_chroma_mc_func avg_chroma_pixels_tab[3];
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#include "version_major.h"
|
#include "version_major.h"
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_MINOR 16
|
#define LIBAVCODEC_VERSION_MINOR 17
|
||||||
#define LIBAVCODEC_VERSION_MICRO 100
|
#define LIBAVCODEC_VERSION_MICRO 100
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||||
|
|
|
||||||
|
|
@ -527,7 +527,7 @@ int ff_vlc_init_multi_from_lengths(VLC *vlc, VLC_MULTI *multi, int nb_bits, int
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
multi->table = av_malloc(sizeof(*multi->table) << nb_bits);
|
multi->table = av_mallocz(sizeof(*multi->table) << nb_bits);
|
||||||
if (!multi->table)
|
if (!multi->table)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ void ff_hevc_idct_ ## W ## _dc_8_ ## opt(int16_t *coeffs); \
|
||||||
void ff_hevc_idct_ ## W ## _dc_10_ ## opt(int16_t *coeffs); \
|
void ff_hevc_idct_ ## W ## _dc_10_ ## opt(int16_t *coeffs); \
|
||||||
void ff_hevc_idct_ ## W ## _dc_12_ ## opt(int16_t *coeffs)
|
void ff_hevc_idct_ ## W ## _dc_12_ ## opt(int16_t *coeffs)
|
||||||
|
|
||||||
IDCT_DC_FUNCS(4x4, mmxext);
|
IDCT_DC_FUNCS(4x4, sse2);
|
||||||
IDCT_DC_FUNCS(8x8, sse2);
|
IDCT_DC_FUNCS(8x8, sse2);
|
||||||
IDCT_DC_FUNCS(16x16, sse2);
|
IDCT_DC_FUNCS(16x16, sse2);
|
||||||
IDCT_DC_FUNCS(32x32, sse2);
|
IDCT_DC_FUNCS(32x32, sse2);
|
||||||
|
|
@ -816,8 +816,6 @@ void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth)
|
||||||
|
|
||||||
if (bit_depth == 8) {
|
if (bit_depth == 8) {
|
||||||
if (EXTERNAL_MMXEXT(cpu_flags)) {
|
if (EXTERNAL_MMXEXT(cpu_flags)) {
|
||||||
c->idct_dc[0] = ff_hevc_idct_4x4_dc_8_mmxext;
|
|
||||||
|
|
||||||
c->add_residual[0] = ff_hevc_add_residual_4_8_mmxext;
|
c->add_residual[0] = ff_hevc_add_residual_4_8_mmxext;
|
||||||
}
|
}
|
||||||
if (EXTERNAL_SSE2(cpu_flags)) {
|
if (EXTERNAL_SSE2(cpu_flags)) {
|
||||||
|
|
@ -832,6 +830,7 @@ void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth)
|
||||||
}
|
}
|
||||||
SAO_BAND_INIT(8, sse2);
|
SAO_BAND_INIT(8, sse2);
|
||||||
|
|
||||||
|
c->idct_dc[0] = ff_hevc_idct_4x4_dc_8_sse2;
|
||||||
c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_sse2;
|
c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_sse2;
|
||||||
c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_sse2;
|
c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_sse2;
|
||||||
c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_sse2;
|
c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_sse2;
|
||||||
|
|
@ -998,7 +997,6 @@ void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth)
|
||||||
} else if (bit_depth == 10) {
|
} else if (bit_depth == 10) {
|
||||||
if (EXTERNAL_MMXEXT(cpu_flags)) {
|
if (EXTERNAL_MMXEXT(cpu_flags)) {
|
||||||
c->add_residual[0] = ff_hevc_add_residual_4_10_mmxext;
|
c->add_residual[0] = ff_hevc_add_residual_4_10_mmxext;
|
||||||
c->idct_dc[0] = ff_hevc_idct_4x4_dc_10_mmxext;
|
|
||||||
}
|
}
|
||||||
if (EXTERNAL_SSE2(cpu_flags)) {
|
if (EXTERNAL_SSE2(cpu_flags)) {
|
||||||
c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_10_sse2;
|
c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_10_sse2;
|
||||||
|
|
@ -1013,6 +1011,7 @@ void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth)
|
||||||
SAO_BAND_INIT(10, sse2);
|
SAO_BAND_INIT(10, sse2);
|
||||||
SAO_EDGE_INIT(10, sse2);
|
SAO_EDGE_INIT(10, sse2);
|
||||||
|
|
||||||
|
c->idct_dc[0] = ff_hevc_idct_4x4_dc_10_sse2;
|
||||||
c->idct_dc[1] = ff_hevc_idct_8x8_dc_10_sse2;
|
c->idct_dc[1] = ff_hevc_idct_8x8_dc_10_sse2;
|
||||||
c->idct_dc[2] = ff_hevc_idct_16x16_dc_10_sse2;
|
c->idct_dc[2] = ff_hevc_idct_16x16_dc_10_sse2;
|
||||||
c->idct_dc[3] = ff_hevc_idct_32x32_dc_10_sse2;
|
c->idct_dc[3] = ff_hevc_idct_32x32_dc_10_sse2;
|
||||||
|
|
@ -1218,9 +1217,6 @@ void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth)
|
||||||
}
|
}
|
||||||
#endif /* HAVE_AVX2_EXTERNAL */
|
#endif /* HAVE_AVX2_EXTERNAL */
|
||||||
} else if (bit_depth == 12) {
|
} else if (bit_depth == 12) {
|
||||||
if (EXTERNAL_MMXEXT(cpu_flags)) {
|
|
||||||
c->idct_dc[0] = ff_hevc_idct_4x4_dc_12_mmxext;
|
|
||||||
}
|
|
||||||
if (EXTERNAL_SSE2(cpu_flags)) {
|
if (EXTERNAL_SSE2(cpu_flags)) {
|
||||||
c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_12_sse2;
|
c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_12_sse2;
|
||||||
c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_12_sse2;
|
c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_12_sse2;
|
||||||
|
|
@ -1231,6 +1227,7 @@ void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth)
|
||||||
SAO_BAND_INIT(12, sse2);
|
SAO_BAND_INIT(12, sse2);
|
||||||
SAO_EDGE_INIT(12, sse2);
|
SAO_EDGE_INIT(12, sse2);
|
||||||
|
|
||||||
|
c->idct_dc[0] = ff_hevc_idct_4x4_dc_12_sse2;
|
||||||
c->idct_dc[1] = ff_hevc_idct_8x8_dc_12_sse2;
|
c->idct_dc[1] = ff_hevc_idct_8x8_dc_12_sse2;
|
||||||
c->idct_dc[2] = ff_hevc_idct_16x16_dc_12_sse2;
|
c->idct_dc[2] = ff_hevc_idct_16x16_dc_12_sse2;
|
||||||
c->idct_dc[3] = ff_hevc_idct_32x32_dc_12_sse2;
|
c->idct_dc[3] = ff_hevc_idct_32x32_dc_12_sse2;
|
||||||
|
|
|
||||||
|
|
@ -273,16 +273,11 @@ cglobal hevc_idct_%1x%1_dc_%2, 1, 2, 1, coeff, tmp
|
||||||
sar tmpd, (15 - %2)
|
sar tmpd, (15 - %2)
|
||||||
movd m0, tmpd
|
movd m0, tmpd
|
||||||
SPLATW m0, xm0
|
SPLATW m0, xm0
|
||||||
mova [coeffq+mmsize*0], m0
|
%assign %%offset 0
|
||||||
mova [coeffq+mmsize*1], m0
|
%rep 2*%1*%1/mmsize
|
||||||
mova [coeffq+mmsize*2], m0
|
mova [coeffq+%%offset], m0
|
||||||
mova [coeffq+mmsize*3], m0
|
%assign %%offset %%offset+mmsize
|
||||||
%if mmsize == 16
|
%endrep
|
||||||
mova [coeffq+mmsize*4], m0
|
|
||||||
mova [coeffq+mmsize*5], m0
|
|
||||||
mova [coeffq+mmsize*6], m0
|
|
||||||
mova [coeffq+mmsize*7], m0
|
|
||||||
%endif
|
|
||||||
RET
|
RET
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
|
|
@ -809,10 +804,8 @@ cglobal hevc_idct_32x32_%1, 1, 6, 16, 256, coeffs
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
%macro INIT_IDCT_DC 1
|
%macro INIT_IDCT_DC 1
|
||||||
INIT_MMX mmxext
|
|
||||||
IDCT_DC_NL 4, %1
|
|
||||||
|
|
||||||
INIT_XMM sse2
|
INIT_XMM sse2
|
||||||
|
IDCT_DC_NL 4, %1
|
||||||
IDCT_DC_NL 8, %1
|
IDCT_DC_NL 8, %1
|
||||||
IDCT_DC 16, 4, %1
|
IDCT_DC 16, 4, %1
|
||||||
IDCT_DC 32, 16, %1
|
IDCT_DC 32, 16, %1
|
||||||
|
|
|
||||||
|
|
@ -1650,7 +1650,7 @@ static const AVOption libplacebo_options[] = {
|
||||||
{"pc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, STATIC, .unit = "range"},
|
{"pc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, STATIC, .unit = "range"},
|
||||||
{"jpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, STATIC, .unit = "range"},
|
{"jpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, STATIC, .unit = "range"},
|
||||||
|
|
||||||
{"color_primaries", "select color primaries", OFFSET(color_primaries), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_PRI_NB-1, DYNAMIC, .unit = "color_primaries"},
|
{"color_primaries", "select color primaries", OFFSET(color_primaries), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_PRI_EXT_NB-1, DYNAMIC, .unit = "color_primaries"},
|
||||||
{"auto", "keep the same color primaries", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
|
{"auto", "keep the same color primaries", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
|
||||||
{"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT709}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
|
{"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT709}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
|
||||||
{"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_UNSPECIFIED}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
|
{"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_UNSPECIFIED}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
|
||||||
|
|
@ -1667,7 +1667,7 @@ static const AVOption libplacebo_options[] = {
|
||||||
{"ebu3213", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_EBU3213}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
|
{"ebu3213", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_EBU3213}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
|
||||||
{"vgamut", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_V_GAMUT}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
|
{"vgamut", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_V_GAMUT}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
|
||||||
|
|
||||||
{"color_trc", "select color transfer", OFFSET(color_trc), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_TRC_NB-1, DYNAMIC, .unit = "color_trc"},
|
{"color_trc", "select color transfer", OFFSET(color_trc), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_TRC_EXT_NB-1, DYNAMIC, .unit = "color_trc"},
|
||||||
{"auto", "keep the same color transfer", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
|
{"auto", "keep the same color transfer", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
|
||||||
{"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT709}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
|
{"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT709}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
|
||||||
{"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_UNSPECIFIED}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
|
{"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_UNSPECIFIED}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
|
||||||
|
|
|
||||||
|
|
@ -196,6 +196,9 @@ void ff_rtp_send_h264_hevc(AVFormatContext *s1, const uint8_t *buf1, int size)
|
||||||
r1 = ff_nal_mp4_find_startcode(r, end, s->nal_length_size);
|
r1 = ff_nal_mp4_find_startcode(r, end, s->nal_length_size);
|
||||||
if (!r1)
|
if (!r1)
|
||||||
r1 = end;
|
r1 = end;
|
||||||
|
// Check that the last is not truncated
|
||||||
|
if (r1 - r < s->nal_length_size)
|
||||||
|
break;
|
||||||
r += s->nal_length_size;
|
r += s->nal_length_size;
|
||||||
} else {
|
} else {
|
||||||
while (!*(r++));
|
while (!*(r++));
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ static void check_idct_dc(HEVCDSPContext *h, int bit_depth)
|
||||||
for (i = 2; i <= 5; i++) {
|
for (i = 2; i <= 5; i++) {
|
||||||
int block_size = 1 << i;
|
int block_size = 1 << i;
|
||||||
int size = block_size * block_size;
|
int size = block_size * block_size;
|
||||||
declare_func_emms(AV_CPU_FLAG_MMXEXT, void, int16_t *coeffs);
|
declare_func(void, int16_t *coeffs);
|
||||||
|
|
||||||
randomize_buffers(coeffs0, size);
|
randomize_buffers(coeffs0, size);
|
||||||
memcpy(coeffs1, coeffs0, sizeof(*coeffs0) * size);
|
memcpy(coeffs1, coeffs0, sizeof(*coeffs0) * size);
|
||||||
|
|
|
||||||
|
|
@ -267,3 +267,16 @@ FATE_FFMPEG-$(call ENCDEC2, MPEG2VIDEO, FFV1, NUT, HSTACK_FILTER PIPE_PROTOCOL F
|
||||||
# test matching by stream disposition
|
# test matching by stream disposition
|
||||||
fate-ffmpeg-spec-disposition: CMD = framecrc -i $(TARGET_SAMPLES)/mpegts/pmtchange.ts -map '0:disp:visual_impaired+descriptions:1' -c copy
|
fate-ffmpeg-spec-disposition: CMD = framecrc -i $(TARGET_SAMPLES)/mpegts/pmtchange.ts -map '0:disp:visual_impaired+descriptions:1' -c copy
|
||||||
FATE_SAMPLES_FFMPEG-$(call FRAMECRC, MPEGTS,,) += fate-ffmpeg-spec-disposition
|
FATE_SAMPLES_FFMPEG-$(call FRAMECRC, MPEGTS,,) += fate-ffmpeg-spec-disposition
|
||||||
|
|
||||||
|
# test heif image merging using internally defined filtegraphs
|
||||||
|
# picking the stream group if not mapping any specific stream
|
||||||
|
fate-ffmpeg-heif-merge: CMD = framecrc -i $(TARGET_SAMPLES)/heif-conformance/C007.heic
|
||||||
|
FATE_SAMPLES_FFMPEG-$(call FRAMECRC, MOV, HEVC, HEVC_PARSER) += fate-ffmpeg-heif-merge
|
||||||
|
|
||||||
|
# mapping the stream group
|
||||||
|
fate-ffmpeg-heif-merge-mapped: CMD = framecrc -i $(TARGET_SAMPLES)/heif-conformance/C007.heic -map '[0:g:0]'
|
||||||
|
FATE_SAMPLES_FFMPEG-$(call FRAMECRC, MOV, HEVC, HEVC_PARSER) += fate-ffmpeg-heif-merge-mapped
|
||||||
|
|
||||||
|
# binding the internal filtegraph with a caller defined filtergraph
|
||||||
|
fate-ffmpeg-heif-merge-filtergraph: CMD = framecrc -i $(TARGET_SAMPLES)/heif-conformance/C007.heic -filter_complex "sws_flags=+accurate_rnd+bitexact\;[0:g:0]scale=w=1280:h=720[out]" -map "[out]"
|
||||||
|
FATE_SAMPLES_FFMPEG-$(call FRAMECRC, MOV, HEVC, HEVC_PARSER SCALE_FILTER) += fate-ffmpeg-heif-merge-filtergraph
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
#tb 0: 1/1
|
||||||
|
#media_type 0: video
|
||||||
|
#codec_id 0: rawvideo
|
||||||
|
#dimensions 0: 2560x1440
|
||||||
|
#sar 0: 0/1
|
||||||
|
0, 0, 0, 1, 5529600, 0x3bf5d001
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
#tb 0: 1/1
|
||||||
|
#media_type 0: video
|
||||||
|
#codec_id 0: rawvideo
|
||||||
|
#dimensions 0: 1280x720
|
||||||
|
#sar 0: 0/1
|
||||||
|
0, 0, 0, 1, 1382400, 0x0f97ebd5
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
#tb 0: 1/1
|
||||||
|
#media_type 0: video
|
||||||
|
#codec_id 0: rawvideo
|
||||||
|
#dimensions 0: 2560x1440
|
||||||
|
#sar 0: 0/1
|
||||||
|
0, 0, 0, 1, 5529600, 0x3bf5d001
|
||||||
Loading…
Reference in New Issue