[FFmpeg-devel] [PATCH] avutil/display: fix inverted doc
--- libavutil/display.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/display.h b/libavutil/display.h index 515adad795..d87bf68425 100644 --- a/libavutil/display.h +++ b/libavutil/display.h @@ -88,7 +88,7 @@ double av_display_rotation_get(const int32_t matrix[9]); /** - * Initialize a transformation matrix describing a pure counterclockwise + * Initialize a transformation matrix describing a pure clockwise * rotation by the specified angle (in degrees). * * @param matrix an allocated transformation matrix (will be fully overwritten -- 2.31.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH] avutil/display: fix inverted doc
Zhao Zhili: > --- > libavutil/display.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/libavutil/display.h b/libavutil/display.h > index 515adad795..d87bf68425 100644 > --- a/libavutil/display.h > +++ b/libavutil/display.h > @@ -88,7 +88,7 @@ > double av_display_rotation_get(const int32_t matrix[9]); > > /** > - * Initialize a transformation matrix describing a pure counterclockwise > + * Initialize a transformation matrix describing a pure clockwise > * rotation by the specified angle (in degrees). > * > * @param matrix an allocated transformation matrix (will be fully > overwritten > If you look at the documentation, you will notice that the matrix returned from the function is supposed to be multiplied from the right to the coordinate (row) vector, not from the left to the coordinate (column) vector as is standard in linear algebra. This is tantamount to transposing the matrix which for rotation matrices means negating the degree. So this doxy is correct. Notice that last time I looked at this, I came to the conclusion that the whole H.2645 SEI parsing code uses it wrongly. - Andreas ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH] avutil/display: fix inverted doc
Andreas Rheinhardt: > Zhao Zhili: >> --- >> libavutil/display.h | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/libavutil/display.h b/libavutil/display.h >> index 515adad795..d87bf68425 100644 >> --- a/libavutil/display.h >> +++ b/libavutil/display.h >> @@ -88,7 +88,7 @@ >> double av_display_rotation_get(const int32_t matrix[9]); >> >> /** >> - * Initialize a transformation matrix describing a pure counterclockwise >> + * Initialize a transformation matrix describing a pure clockwise >> * rotation by the specified angle (in degrees). >> * >> * @param matrix an allocated transformation matrix (will be fully >> overwritten >> > > If you look at the documentation, you will notice that the matrix > returned from the function is supposed to be multiplied from the right > to the coordinate (row) vector, not from the left to the coordinate > (column) vector as is standard in linear algebra. This is tantamount to > transposing the matrix which for rotation matrices means negating the > degree. So this doxy is correct. > Notice that last time I looked at this, I came to the conclusion that > the whole H.2645 SEI parsing code uses it wrongly. > Wait, there is another difference to ordinary linear algebra: The y axis is directed downwards. Maybe you are right. Let me think this through... - Andreas ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v5 4/6] lavc: Implement Dolby Vision RPU parsing
From: Niklas Haas Based on a mixture of guesswork, partial documentation in patents, and reverse engineering of real-world samples. Confirmed working for all the samples I've thrown at it. Contains some annoying machinery to persist these values in between frames, which is needed in theory even though I've never actually seen a sample that relies on it in practice. May or may not work. Since the distinction matters greatly for parsing the color matrix values, this includes a small helper function to guess the right profile from the RPU itself in case the user has forgotten to forward the dovi configuration record to the decoder. (Which in practice, only ffmpeg.c and ffplay do..) Notable omissions / deviations: - CRC32 verification. This is based on the MPEG2 CRC32 type, which does not seem to be implemented in lavu. (And I don't care enough to do so) - Linear interpolation support. Nothing documents this (beyond its existence) and no samples use it, so impossible to implement. - All of the extension metadata blocks, but these contain values that seem largely congruent with ST2094, HDR10, or other existing forms of side data, so I will defer parsing/attaching them to a future commit. - The patent describes a mechanism for predicting coefficients from previous RPUs, but the bit for the flag whether to use the prediction deltas or signal entirely new coefficients does not seem to be present in actual RPUs, so we ignore this subsystem entirely. - In the patent's spec, the NLQ subsystem also loops over num_nlq_pivots, but even in the patent the number is hard-coded to one iteration rather than signalled. So we only store one set of coefs. Heavily influenced by https://github.com/quietvoid/dovi_tool Documentation drawn from US Patent 10,701,399 B2 and ETSI GS CCM 001 Signed-off-by: Niklas Haas --- configure | 2 + libavcodec/Makefile | 1 + libavcodec/dovi_rpu.c | 432 ++ libavcodec/dovi_rpu.h | 71 +++ 4 files changed, 506 insertions(+) create mode 100644 libavcodec/dovi_rpu.c create mode 100644 libavcodec/dovi_rpu.h diff --git a/configure b/configure index a7593ec2db..b8c9c5d2ae 100755 --- a/configure +++ b/configure @@ -2426,6 +2426,7 @@ CONFIG_EXTRA=" cbs_vp9 dirac_parse dnn +dovi_rpu dvprofile exif faandct @@ -2693,6 +2694,7 @@ cbs_mpeg2_select="cbs" cbs_vp9_select="cbs" dct_select="rdft" dirac_parse_select="golomb" +dovi_rpu_select="golomb" dnn_suggest="libtensorflow libopenvino" dnn_deps="avformat swscale" error_resilience_select="me_cmp" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 4122a9b144..127e5db7df 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -77,6 +77,7 @@ OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o +OBJS-$(CONFIG_DOVI_RPU)+= dovi_rpu.o OBJS-$(CONFIG_ERROR_RESILIENCE)+= error_resilience.o OBJS-$(CONFIG_EXIF)+= exif.o tiff_common.o OBJS-$(CONFIG_FAANDCT) += faandct.o diff --git a/libavcodec/dovi_rpu.c b/libavcodec/dovi_rpu.c new file mode 100644 index 00..e3c860464e --- /dev/null +++ b/libavcodec/dovi_rpu.c @@ -0,0 +1,432 @@ +/* + * Dolby Vision RPU decoder + * + * Copyright (C) 2021 Jan Ekström + * Copyright (C) 2021 Niklas Haas + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/buffer.h" + +#include "dovi_rpu.h" +#include "golomb.h" +#include "get_bits.h" + +enum { +RPU_COEFF_FIXED = 0, +RPU_COEFF_FLOAT = 1, +}; + +/** + * Private contents of vdr_ref. + */ +typedef struct DOVIVdrRef { +AVDOVIDataMapping mapping; +AVDOVIColorMetadata color; +} DOVIVdrRef; + +void ff_dovi_ctx_unref(DOVIContext *s) +{ +for (int i = 0; i < DOVI_MAX_DM_ID; i++) +av_buffer_unref(&s->vdr_ref[i]); + +/* Preserve the user-provided fields explicitly, reset everything else */ +*s = (DOVIContext) { +.avctx = s->avctx, +.config = s->config, +}; +} + +int ff_dovi_ctx_replace(DOVIContext *s, const DOVIContext *s
[FFmpeg-devel] [PATCH v5 3/6] ffprobe: Support AV_FRAME_DATA_DOVI_METADATA
From: Jan Ekström Co-authored-by: Niklas Haas --- fftools/ffprobe.c | 173 +- 1 file changed, 170 insertions(+), 3 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 0711e02922..75263cd3a9 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -175,6 +175,10 @@ typedef enum { SECTION_ID_FRAME_SIDE_DATA, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_TIMECODE, +SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, +SECTION_ID_FRAME_SIDE_DATA_COMPONENT, +SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, +SECTION_ID_FRAME_SIDE_DATA_PIECE, SECTION_ID_FRAME_LOG, SECTION_ID_FRAME_LOGS, SECTION_ID_LIBRARY_VERSION, @@ -219,9 +223,13 @@ static struct section sections[] = { [SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_LOGS, -1 } }, [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" }, [SECTION_ID_FRAME_SIDE_DATA_LIST] ={ SECTION_ID_FRAME_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "frame_side_data_list" }, -[SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", 0, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, -1 } }, -[SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, "timecodes", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, -1 } }, -[SECTION_ID_FRAME_SIDE_DATA_TIMECODE] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, "timecode", 0, { -1 } }, +[SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", 0, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 } }, +[SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, "timecodes", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, -1 } }, +[SECTION_ID_FRAME_SIDE_DATA_TIMECODE] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, "timecode", 0, { -1 } }, +[SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, "components", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, -1 } }, +[SECTION_ID_FRAME_SIDE_DATA_COMPONENT] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, "component", 0, { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, -1 } }, +[SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, "pieces", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_PIECE, -1 } }, +[SECTION_ID_FRAME_SIDE_DATA_PIECE] ={ SECTION_ID_FRAME_SIDE_DATA_PIECE, "section", 0, { -1 } }, [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } }, [SECTION_ID_FRAME_LOG] = { SECTION_ID_FRAME_LOG, "log", 0, { -1 }, }, [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } }, @@ -1807,6 +1815,16 @@ static void writer_register_all(void) writer_print_string(w, k, pbuf.str, 0);\ } while (0) +#define print_list_fmt(k, f, n, ...) do { \ +av_bprint_clear(&pbuf); \ +for (int idx = 0; idx < n; idx++) { \ +if (idx > 0)\ +av_bprint_chars(&pbuf, ' ', 1); \ +av_bprintf(&pbuf, f, __VA_ARGS__); \ +} \ +writer_print_string(w, k, pbuf.str, 0); \ +} while (0) + #define print_int(k, v) writer_print_integer(w, k, v) #define print_q(k, v, s)writer_print_rational(w, k, v, s) #define print_str(k, v) writer_print_string(w, k, v, 0) @@ -1852,6 +1870,153 @@ static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id return ret; } +static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi) +{ +if (!dovi) +return; + +{ +const AVDOVIRpuDataHeader *hdr = &dovi->header; +const AVDOVIDataMapping *mapping = &dovi->mapping; +const AVDOVIColorMetadata *color = &dovi->color; +AVBPrint pbuf; + +av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED); + +// header +print_int("rpu_type",hdr->rpu_type); +print_int("rpu_format", hdr->rpu_format); +print_int("vdr_rpu_profile", hdr->vdr_rpu_profile); +print_int("vdr_rpu_level", hdr->vdr_rpu_level); +print_int("chroma_resampling_explicit_filter_flag", + hdr->chroma_resampling_explicit_filter_flag); +print_int("coef_data_type", hdr->coef_data_type); +print_int("coef_log2_denom",
[FFmpeg-devel] [PATCH v5 2/6] lavfi/showinfo: Support AV_FRAME_DATA_DOVI_METADATA
From: Niklas Haas Signed-off-by: Niklas Haas --- libavfilter/vf_showinfo.c | 108 ++ 1 file changed, 108 insertions(+) diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index 62c7833247..8a7efc15b7 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -27,6 +27,7 @@ #include "libavutil/bswap.h" #include "libavutil/adler32.h" #include "libavutil/display.h" +#include "libavutil/dovi_meta.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/film_grain_params.h" @@ -429,6 +430,110 @@ static void dump_sei_film_grain_params_metadata(AVFilterContext *ctx, const AVFr } } +static void dump_dovi_metadata(AVFilterContext *ctx, const AVFrameSideData *sd) +{ +const AVDOVIMetadata *dovi = (const AVDOVIMetadata *) sd->data; +const AVDOVIRpuDataHeader *hdr = &dovi->header; +const AVDOVIDataMapping *mapping = &dovi->mapping; +const AVDOVIColorMetadata *color = &dovi->color; + +av_log(ctx, AV_LOG_INFO, "Dolby Vision Metadata:\n"); +av_log(ctx, AV_LOG_INFO, "rpu_type=%"PRIu8"; ", hdr->rpu_type); +av_log(ctx, AV_LOG_INFO, "rpu_format=%"PRIu16"; ", hdr->rpu_format); +av_log(ctx, AV_LOG_INFO, "vdr_rpu_profile=%"PRIu8"; ", hdr->vdr_rpu_profile); +av_log(ctx, AV_LOG_INFO, "vdr_rpu_level=%"PRIu8"; ", hdr->vdr_rpu_level); +av_log(ctx, AV_LOG_INFO, "chroma_resampling_explicit_filter_flag=%d; ", hdr->chroma_resampling_explicit_filter_flag); +av_log(ctx, AV_LOG_INFO, "coef_data_type=%"PRIu8"; ", hdr->coef_data_type); +av_log(ctx, AV_LOG_INFO, "coef_log2_denom=%"PRIu8"; ", hdr->coef_log2_denom); +av_log(ctx, AV_LOG_INFO, "vdr_rpu_normalized_idc=%"PRIu8"; ", hdr->vdr_rpu_normalized_idc); +av_log(ctx, AV_LOG_INFO, "bl_video_full_range_flag=%d; ", hdr->bl_video_full_range_flag); +av_log(ctx, AV_LOG_INFO, "bl_bit_depth=%"PRIu8"; ", hdr->bl_bit_depth); +av_log(ctx, AV_LOG_INFO, "el_bit_depth=%"PRIu8"; ", hdr->el_bit_depth); +av_log(ctx, AV_LOG_INFO, "vdr_bit_depth=%"PRIu8"; ", hdr->vdr_bit_depth); +av_log(ctx, AV_LOG_INFO, "spatial_resampling_filter_flag=%d; ", hdr->spatial_resampling_filter_flag); +av_log(ctx, AV_LOG_INFO, "el_spatial_resampling_filter_flag=%d; ", hdr->el_spatial_resampling_filter_flag); +av_log(ctx, AV_LOG_INFO, "disable_residual_flag=%d\n", hdr->disable_residual_flag); + +av_log(ctx, AV_LOG_INFO, "data mapping: "); +av_log(ctx, AV_LOG_INFO, "vdr_rpu_id=%"PRIu8"; ", mapping->vdr_rpu_id); +av_log(ctx, AV_LOG_INFO, "mapping_color_space=%"PRIu8"; ", mapping->mapping_color_space); +av_log(ctx, AV_LOG_INFO, "mapping_chroma_format_idc=%"PRIu8"; ", mapping->mapping_chroma_format_idc); +av_log(ctx, AV_LOG_INFO, "nlq_method_idc=%d; ", (int) mapping->nlq_method_idc); +av_log(ctx, AV_LOG_INFO, "num_x_partitions=%"PRIu32"; ", mapping->num_x_partitions); +av_log(ctx, AV_LOG_INFO, "num_y_partitions=%"PRIu32"\n", mapping->num_y_partitions); + +for (int c = 0; c < 3; c++) { +const AVDOVIReshapingCurve *curve = &mapping->curves[c]; +const AVDOVINLQParams *nlq = &mapping->nlq[c]; +av_log(ctx, AV_LOG_INFO, " channel %d: ", c); +av_log(ctx, AV_LOG_INFO, "pivots={ "); +for (int i = 0; i < curve->num_pivots; i++) +av_log(ctx, AV_LOG_INFO, "%"PRIu16" ", curve->pivots[i]); +av_log(ctx, AV_LOG_INFO, "}; mapping_idc={ "); +for (int i = 0; i < curve->num_pivots - 1; i++) +av_log(ctx, AV_LOG_INFO, "%d ", (int) curve->mapping_idc[i]); +av_log(ctx, AV_LOG_INFO, "}; poly_order={ "); +for (int i = 0; i < curve->num_pivots - 1; i++) +av_log(ctx, AV_LOG_INFO, "%"PRIu8" ", curve->poly_order[i]); +av_log(ctx, AV_LOG_INFO, "}; poly_coef={ "); +for (int i = 0; i < curve->num_pivots - 1; i++) { +av_log(ctx, AV_LOG_INFO, "{%"PRIi64", %"PRIi64", %"PRIi64"} ", + curve->poly_coef[i][0], + curve->poly_coef[i][1], + curve->poly_coef[i][2]); +} + +av_log(ctx, AV_LOG_INFO, "}; mmr_order={ "); +for (int i = 0; i < curve->num_pivots - 1; i++) +av_log(ctx, AV_LOG_INFO, "%"PRIu8" ", curve->mmr_order[i]); +av_log(ctx, AV_LOG_INFO, "}; mmr_constant={ "); +for (int i = 0; i < curve->num_pivots - 1; i++) +av_log(ctx, AV_LOG_INFO, "%"PRIi64" ", curve->mmr_constant[i]); +av_log(ctx, AV_LOG_INFO, "}; mmr_coef={ "); +for (int i = 0; i < curve->num_pivots - 1; i++) { +av_log(ctx, AV_LOG_INFO, "{"); +for (int j = 0; j < curve->mmr_order[i]; j++) { +for (int k = 0; k < 7; k++) +av_log(ctx, AV_LOG_INFO, "%"PRIi64" ", curve->mmr_coef[i][j][k]); +} +av_log(ctx, AV_LOG_INFO, "} "); +} + +av_log(ctx, AV_LOG_INFO, "}; nlq_offset=%"PRIu64"; ", nlq->nlq_offset); +
[FFmpeg-devel] [PATCH v5 1/6] lavu/frame: Add Dolby Vision metadata side data type
From: Niklas Haas Signed-off-by: Niklas Haas --- doc/APIchanges| 3 + libavutil/dovi_meta.c | 12 libavutil/dovi_meta.h | 132 ++ libavutil/frame.c | 1 + libavutil/frame.h | 9 ++- libavutil/version.h | 2 +- 6 files changed, 157 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 17aa664ca3..0ddde40bdf 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2021-12-xx - xx - lavu 57.12.100 - frame.h + Add AV_FRAME_DATA_DOVI_RESHAPING. + 2021-12-xx - xx - lavf 59.10.100 - avformat.h Add AVFormatContext io_close2 which returns an int diff --git a/libavutil/dovi_meta.c b/libavutil/dovi_meta.c index 7bd08f6c54..60b4cb2376 100644 --- a/libavutil/dovi_meta.c +++ b/libavutil/dovi_meta.c @@ -33,3 +33,15 @@ AVDOVIDecoderConfigurationRecord *av_dovi_alloc(size_t *size) return dovi; } + +AVDOVIMetadata *av_dovi_metadata_alloc(size_t *size) +{ +AVDOVIMetadata *dovi = av_mallocz(sizeof(AVDOVIMetadata)); +if (!dovi) +return NULL; + +if (size) +*size = sizeof(*dovi); + +return dovi; +} diff --git a/libavutil/dovi_meta.h b/libavutil/dovi_meta.h index 299911d434..20efd41676 100644 --- a/libavutil/dovi_meta.h +++ b/libavutil/dovi_meta.h @@ -29,6 +29,7 @@ #include #include +#include "rational.h" /* * DOVI configuration @@ -67,4 +68,135 @@ typedef struct AVDOVIDecoderConfigurationRecord { */ AVDOVIDecoderConfigurationRecord *av_dovi_alloc(size_t *size); +/** + * Dolby Vision RPU data header. + */ +typedef struct AVDOVIRpuDataHeader { +uint8_t rpu_type; +uint16_t rpu_format; +uint8_t vdr_rpu_profile; +uint8_t vdr_rpu_level; +int chroma_resampling_explicit_filter_flag; +uint8_t coef_data_type; /* informative, lavc always converts to fixed */ +uint8_t coef_log2_denom; +uint8_t vdr_rpu_normalized_idc; +int bl_video_full_range_flag; +uint8_t bl_bit_depth; /* [8, 16] */ +uint8_t el_bit_depth; /* [8, 16] */ +uint8_t vdr_bit_depth; /* [8, 16] */ +int spatial_resampling_filter_flag; +int el_spatial_resampling_filter_flag; +int disable_residual_flag; +} AVDOVIRpuDataHeader; + +enum AVDOVIMappingMethod { +AV_DOVI_MAPPING_POLYNOMIAL = 0, +AV_DOVI_MAPPING_MMR = 1, +}; + +/** + * Coefficients of a piece-wise function. The pieces of the function span the + * value ranges between two adjacent pivot values. + */ +#define FF_DOVI_MAX_PIECES 8 +typedef struct AVDOVIReshapingCurve { +uint8_t num_pivots; /* [2, 9] */ +uint16_t pivots[FF_DOVI_MAX_PIECES + 1];/* sorted ascending */ +enum AVDOVIMappingMethod mapping_idc[FF_DOVI_MAX_PIECES]; +/* AV_DOVI_MAPPING_POLYNOMIAL */ +uint8_t poly_order[FF_DOVI_MAX_PIECES]; /* [1, 2] */ +int64_t poly_coef[FF_DOVI_MAX_PIECES][3]; /* x^0, x^1, x^2 */ +/* AV_DOVI_MAPPING_MMR */ +uint8_t mmr_order[FF_DOVI_MAX_PIECES]; /* [1, 3] */ +int64_t mmr_constant[FF_DOVI_MAX_PIECES]; +int64_t mmr_coef[FF_DOVI_MAX_PIECES][3/* order - 1 */][7]; +} AVDOVIReshapingCurve; + +enum AVDOVINLQMethod { +AV_DOVI_NLQ_NONE = -1, +AV_DOVI_NLQ_LINEAR_DZ = 0, +}; + +/** + * Coefficients of the non-linear inverse quantization. For the interpretation + * of these, see ETSI GS CCM 001. + */ +typedef struct AVDOVINLQParams { +uint64_t nlq_offset; +uint64_t vdr_in_max; +/* AV_DOVI_NLQ_LINEAR_DZ */ +uint64_t linear_deadzone_slope; +uint64_t linear_deadzone_threshold; +} AVDOVINLQParams; + +/** + * Dolby Vision RPU data mapping parameters. + */ +typedef struct AVDOVIDataMapping { +uint8_t vdr_rpu_id; +uint8_t mapping_color_space; +uint8_t mapping_chroma_format_idc; +AVDOVIReshapingCurve curves[3]; /* per component */ + +/* Non-linear inverse quantization */ +enum AVDOVINLQMethod nlq_method_idc; +uint32_t num_x_partitions; +uint32_t num_y_partitions; +AVDOVINLQParams nlq[3]; /* per component */ +} AVDOVIDataMapping; + +typedef struct AVDOVIColorMetadata { +uint8_t dm_metadata_id; +int scene_refresh_flag; + +/** + * Coefficients of the custom Dolby Vision IPT-PQ matrices. These are to be + * used instead of the matrices indicated by the frame's colorspace tags. + * The output of rgb_to_lms_matrix is to be fed into a BT.2020 LMS->RGB + * matrix based on a Hunt-Pointer-Estevez transform, but without any + * crosstalk. (See the definition of the ICtCp colorspace for more + * information.) + */ +AVRational ycc_to_rgb_matrix[9]; /* before PQ linearization */ +AVRational ycc_to_rgb_offset[3]; /* input offset of neutral value */ +AVRational rgb_to_lms_matrix[9]; /* after PQ linearization */ + +/** + * Extra signal metadata (see Dolby patents for more info). + */ +uint16_t signal_eotf; +uint16_t signal_eotf_param0; +u
[FFmpeg-devel] [PATCH v5 5/6] fate: Limit Dolby Vision RPU test frame count
From: Niklas Haas To avoid the ref for this growing to a very large size when attaching the parsed RPU side data. Since this sample does not have any dynamic metadata, two frames will serve just as well as 100. Signed-off-by: Niklas Haas --- tests/fate/hevc.mak| 2 +- tests/ref/fate/hevc-dv-rpu | 499 - 2 files changed, 1 insertion(+), 500 deletions(-) diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak index abe4264662..95dcf5bfc5 100644 --- a/tests/fate/hevc.mak +++ b/tests/fate/hevc.mak @@ -273,7 +273,7 @@ FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-monochrome-crop fate-hevc-hdr10-plus-metadata: CMD = probeframes -show_entries frame=side_data_list $(TARGET_SAMPLES)/hevc/hdr10_plus_h265_sample.hevc FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-hdr10-plus-metadata -fate-hevc-dv-rpu: CMD = probeframes -show_entries frame=side_data_list -select_streams 0 $(TARGET_SAMPLES)/hevc/dv84.mov +fate-hevc-dv-rpu: CMD = probeframes -show_entries frame=side_data_list -select_streams 0 -read_intervals "%+\#2" $(TARGET_SAMPLES)/hevc/dv84.mov FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-dv-rpu fate-hevc-two-first-slice: CMD = threads=2 framemd5 -i $(TARGET_SAMPLES)/hevc/two_first_slice.mp4 -sws_flags bitexact -t 00:02.00 -an diff --git a/tests/ref/fate/hevc-dv-rpu b/tests/ref/fate/hevc-dv-rpu index 37ad9ffec2..416d9c51a6 100644 --- a/tests/ref/fate/hevc-dv-rpu +++ b/tests/ref/fate/hevc-dv-rpu @@ -11,502 +11,3 @@ side_data_type=Dolby Vision RPU Data side_data_type=Dolby Vision RPU Data [/SIDE_DATA] [/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=H.26[45] User Data Unregistered SEI message -[/SIDE_DATA] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME] -[SIDE_DATA] -side_data_type=Dolby Vision RPU Data -[/SIDE_DATA] -[/FRAME] -[FRAME]
[FFmpeg-devel] [PATCH v5 6/6] lavc/hevcdec: Parse DOVI RPU NALs
From: Niklas Haas And expose the parsed values as frame side data. Update FATE results to match. It's worth documenting that this relies on the dovi configuration record being present on the first AVPacket fed to the decoder, which in practice is the case if if the API user has called something like av_format_inject_global_side_data, which is unfortunately not the default. This commit is not the time and place to change that behavior, though. Signed-off-by: Niklas Haas --- configure | 2 +- libavcodec/hevcdec.c | 62 -- libavcodec/hevcdec.h | 3 + tests/ref/fate/hevc-dv-rpu | 224 + 4 files changed, 282 insertions(+), 9 deletions(-) diff --git a/configure b/configure index b8c9c5d2ae..d4336d20f5 100755 --- a/configure +++ b/configure @@ -2813,7 +2813,7 @@ h264_decoder_suggest="error_resilience" hap_decoder_select="snappy texturedsp" hap_encoder_deps="libsnappy" hap_encoder_select="texturedspenc" -hevc_decoder_select="atsc_a53 bswapdsp cabac golomb hevcparse videodsp" +hevc_decoder_select="atsc_a53 bswapdsp cabac dovi_rpu golomb hevcparse videodsp" huffyuv_decoder_select="bswapdsp huffyuvdsp llviddsp" huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp llvidencdsp" hymt_decoder_select="huffyuv_decoder" diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 46d9edf8eb..82410ae5cc 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2723,6 +2723,7 @@ error: static int set_side_data(HEVCContext *s) { AVFrame *out = s->ref->frame; +int ret; if (s->sei.frame_packing.present && s->sei.frame_packing.arrangement_type >= 3 && @@ -2967,6 +2968,9 @@ static int set_side_data(HEVCContext *s) s->rpu_buf = NULL; } +if ((ret = ff_dovi_attach_side_data(&s->dovi_ctx, out)) < 0) +return ret; + return 0; } @@ -3298,16 +3302,23 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) if (s->pkt.nb_nals > 1 && s->pkt.nals[s->pkt.nb_nals - 1].type == HEVC_NAL_UNSPEC62 && s->pkt.nals[s->pkt.nb_nals - 1].size > 2 && !s->pkt.nals[s->pkt.nb_nals - 1].nuh_layer_id && !s->pkt.nals[s->pkt.nb_nals - 1].temporal_id) { +H2645NAL *nal = &s->pkt.nals[s->pkt.nb_nals - 1]; if (s->rpu_buf) { av_buffer_unref(&s->rpu_buf); av_log(s->avctx, AV_LOG_WARNING, "Multiple Dolby Vision RPUs found in one AU. Skipping previous.\n"); } -s->rpu_buf = av_buffer_alloc(s->pkt.nals[s->pkt.nb_nals - 1].raw_size - 2); +s->rpu_buf = av_buffer_alloc(nal->raw_size - 2); if (!s->rpu_buf) return AVERROR(ENOMEM); +memcpy(s->rpu_buf->data, nal->raw_data + 2, nal->raw_size - 2); -memcpy(s->rpu_buf->data, s->pkt.nals[s->pkt.nb_nals - 1].raw_data + 2, s->pkt.nals[s->pkt.nb_nals - 1].raw_size - 2); +ret = ff_dovi_rpu_parse(&s->dovi_ctx, nal->data + 2, nal->size - 2); +if (ret < 0) { +av_buffer_unref(&s->rpu_buf); +av_log(s->avctx, AV_LOG_WARNING, "Error parsing DOVI NAL unit.\n"); +/* ignore */ +} } /* decode the NAL units */ @@ -3440,8 +3451,8 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, AVPacket *avpkt) { int ret; -size_t new_extradata_size; -uint8_t *new_extradata; +uint8_t *sd; +size_t sd_size; HEVCContext *s = avctx->priv_data; if (!avpkt->size) { @@ -3453,14 +3464,37 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, return 0; } -new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, -&new_extradata_size); -if (new_extradata && new_extradata_size > 0) { -ret = hevc_decode_extradata(s, new_extradata, new_extradata_size, 0); +sd = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &sd_size); +if (sd && sd_size > 0) { +ret = hevc_decode_extradata(s, sd, sd_size, 0); if (ret < 0) return ret; } +sd = av_packet_get_side_data(avpkt, AV_PKT_DATA_DOVI_CONF, &sd_size); +if (sd && sd_size > 0) { +if (s->dovi_cfg) { +/* Reuse existing buffer */ +if ((ret = av_buffer_make_writable(&s->dovi_cfg)) < 0) +return ret; +} else { +/* Allocate new buffer */ +AVDOVIDecoderConfigurationRecord *cfg; +size_t cfg_size; +cfg = av_dovi_alloc(&cfg_size); +if (!cfg) +return AVERROR(ENOMEM); +s->dovi_cfg = av_buffer_create((uint8_t *) cfg, cfg_size, NULL, NULL, 0); +if (!s->dovi_cfg) { +av_free(cfg); +return AVERROR(ENOMEM); +} +} + +av_assert0(sd_size >= s->dovi_cfg->size); +memcpy(s->d
Re: [FFmpeg-devel] [PATCH v2] lavfi/drawtext: Add localtime_ms for millisecond precision
On 11 Dec 2021, at 23:17, Andreas Rheinhardt wrote: Thilo Borgmann: On 10 Dec 2021, at 17:46, Michael Niedermayer wrote: On Fri, Dec 10, 2021 at 12:36:21PM +0100, Thilo Borgmann wrote: On 10 Dec 2021, at 3:47, zhilizhao(赵志立) wrote: On Dec 10, 2021, at 3:11 AM, Thilo Borgmann wrote: Hi, add %{localtime_ms}, %{gmtime_ms} functions to the drawtext filter. Same as %{localtime}/%{gmtime} but with additional millisecond part. sorry for delay, second version including review remarks: -get timing once -also add gmtime_ms instead of just localtime_ms + if (tag == 'M' || tag == 'm') { + char ms[5] = {0}; + int64_t dnow = (unow - ((int64_t)now) * 100) / 1000; + snprintf(ms, 5, ".%03d", (int)dnow); + av_bprint_append_data(bp, ms, 4); + } How about av_bprintf(&bp, ".%03d", (int)(unow % 100) / 1000); Makes way too much sense. I need holidays… Attached v3. Thanks! -Thilo doc/filters.texi | 8 libavfilter/vf_drawtext.c | 12 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) 87d34e4106b829d42c5e57c847c28bed08bf3a81 v3-0001-lavfi-drawtext-Add-localtime_ms-for-millisecond-p.patch From fd34d1434e2243a881c24f6db4cc0db92289f4bb Mon Sep 17 00:00:00 2001 From: Thilo Borgmann Date: Fri, 10 Dec 2021 12:34:23 +0100 Subject: [PATCH v3] lavfi/drawtext: Add localtime_ms for millisecond precision Iam missining something here as it doesnt build AR libavdevice/libavdevice.a CC libavfilter/vf_drawtext.o libavfilter/vf_drawtext.c: In function ‘func_strftime’: libavfilter/vf_drawtext.c:1052:12: error: implicit declaration of function ‘av_gettime’; did you mean ‘av_get_token’? [-Werror=implicit-function-declaration] unow = av_gettime(); ^~ av_get_token libavfilter/vf_drawtext.c:1061:20: warning: passing argument 1 of ‘av_bprintf’ from incompatible pointer type [-Wincompatible-pointer-types] av_bprintf(&bp, ".%03d", (int)(unow % 100) / 1000); ^ In file included from libavfilter/vf_drawtext.c:47:0: ./libavutil/bprint.h:127:6: note: expected ‘AVBPrint * {aka struct AVBPrint *}’ but argument is of type ‘AVBPrint ** {aka struct AVBPrint **}’ void av_bprintf(AVBPrint *buf, const char *fmt, ...) av_printf_format(2, 3); ^~ cc1: some warnings being treated as errors ffbuild/common.mak:70: recipe for target 'libavfilter/vf_drawtext.o' failed make: *** [libavfilter/vf_drawtext.o] Error 1 Works for me on OSX. av_gettime() is in lavu/time.c which gets included via lavu/time_internal.h…. av_gettime() is public and resides in lavu/time.h, not lavu/time_internal.h; the latter does not include the former in any way. Ups, was it… But compat/os2threads.h and compat/w32pthreads.h include lavu/time.h. Maybe you have it from the former? It doesn't work here (Ubuntu 21.10) either. Retested and I got no clue how this appeared to be working for me yesterday - sorry. v4 attached, including lavu/time.h and fixed pointer type warning. Thanks! -ThiloFrom 9b70c93c754fa4cd1b55fd3967910727f685a6b6 Mon Sep 17 00:00:00 2001 From: Thilo Borgmann Date: Sun, 12 Dec 2021 16:17:03 +0100 Subject: [PATCH v4] lavfi/drawtext: Add localtime_ms for millisecond precision Suggested-By: ffm...@fb.com --- doc/filters.texi | 8 libavfilter/vf_drawtext.c | 13 +++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 78faf76..db75632 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -10949,10 +10949,18 @@ It can be used to add padding with zeros from the left. The time at which the filter is running, expressed in UTC. It can accept an argument: a strftime() format string. +@item gmtime_ms +Same as @code{gmtime} but with millisecond precision. +It can accept an argument: a strftime() format string. + @item localtime The time at which the filter is running, expressed in the local time zone. It can accept an argument: a strftime() format string. +@item localtime_ms +Same as @code{localtime} but with millisecond precision. +It can accept an argument: a strftime() format string. + @item metadata Frame metadata. Takes one or two arguments. diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 382d589..d047a8c 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -51,6 +51,7 @@ #include "libavutil/opt.h" #include "libavutil/random_seed.h" #include "libavutil/parseutils.h" +#include "libavutil/time.h" #include "libavutil/timecode.h" #include "libavutil/time_internal.h" #include "libavutil/tree.h" @@ -1045,15 +1046,21 @@ static int func_strftime(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag) { const char *fmt = argc ? argv[0] : "%Y-%m-%d %H:%M:%S"; +int64_t unow; time_t now; struct tm tm; -time(&now); -if (tag == 'L') +
Re: [FFmpeg-devel] Politics
> yesterday, it happened for the 4th and 5th times that another developer > called my patchset a “hack”. Hope it wasn't me. If I did, I'm sorry, didn't wanted to imply bad code or lack of skills, or anything: I was trying to understand if there's some way to actually unblock your patchset. And the quicker the way, the better. > subtitle_pts LOL... that's some elegant answer. I have my own doubts about subtitle_pts, but that's exactly why I wouldn't call it "hack": because I don't fully grasp it yet. I've read some devs arguments (not all) against it, but it also wasn't clear for me back then why the strong backlash. Some seemed just conservative and/or idealists, others didn't seem to value live-streaming as a first class citizen between use cases. Can't tell if they were right or wrong, or myself at reading them. But mixed feelings for sure. Howerver, *if* subtitle_pts is truly the last point against softworkz patchset, then it's very close to see the light, and that's exciting. I have a strong bias towards softworkz code, because I value non-breaking newer use cases over quality of design. This is what I see: - The problems softworkz mentions with live subtitles are VERY real. - I can't defend subtitle_pts, at least yet, because I don't get it. - If it solves live-streaming subtitles problems, and doesn't break anything else, it's fine by me. But if there's some consensus between established community figures against that property and that blocks the release, well... removing the property sounds like the quickest path. Will test it during week. Now, the question remains: are we sure subtitle_pts is the last barrier here? ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] Politics
Daniel Cantarín (12021-12-12): > Howerver, *if* subtitle_pts is truly the last point against softworkz > patchset, then it's very close to see the light, and that's exciting. Far from it. I have pointed the core flaws with the design a few times, but having been received with rudeness, I did not bother insisting. This patch series is nowhere near anything that can be accepted. Regards, -- Nicolas George signature.asc Description: PGP signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 1/3] avcodec/speedhq: Replace always-true check by assert
Should fix Coverity tickets #1473572 and #1473504. Signed-off-by: Andreas Rheinhardt --- libavcodec/speedhq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/speedhq.c b/libavcodec/speedhq.c index 91ba80ebd3..743dacc6ce 100644 --- a/libavcodec/speedhq.c +++ b/libavcodec/speedhq.c @@ -295,7 +295,8 @@ static int decode_speedhq_border(const SHQContext *s, GetBitContext *gb, AVFrame if (s->subsampling == SHQ_SUBSAMPLING_420) { dest_cb = frame->data[1] + frame->linesize[1] * (y/2 + field_number) + x / 2; dest_cr = frame->data[2] + frame->linesize[2] * (y/2 + field_number) + x / 2; -} else if (s->subsampling == SHQ_SUBSAMPLING_422) { +} else { +av_assert2(s->subsampling == SHQ_SUBSAMPLING_422); dest_cb = frame->data[1] + frame->linesize[1] * (y + field_number) + x / 2; dest_cr = frame->data[2] + frame->linesize[2] * (y + field_number) + x / 2; } -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 2/3] avformat/moflex: Free AVPackets via av_packet_free() on error
(This is not a leak as long as av_free() completely frees blank packets.) Signed-off-by: Andreas Rheinhardt --- libavformat/moflex.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/moflex.c b/libavformat/moflex.c index 234b0fb06e..67adebe5e0 100644 --- a/libavformat/moflex.c +++ b/libavformat/moflex.c @@ -383,4 +383,5 @@ const AVInputFormat ff_moflex_demuxer = { .read_close = moflex_read_close, .extensions = "moflex", .flags = AVFMT_GENERIC_INDEX, +.flags_internal = FF_FMT_INIT_CLEANUP, }; -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 3/3] avformat/moflex: Don't use uninitialized timebase for data stream
Signed-off-by: Andreas Rheinhardt --- libavformat/moflex.c | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libavformat/moflex.c b/libavformat/moflex.c index 67adebe5e0..1d342417f7 100644 --- a/libavformat/moflex.c +++ b/libavformat/moflex.c @@ -172,7 +172,7 @@ static int moflex_read_sync(AVFormatContext *s) unsigned type, ssize, codec_id = 0; unsigned codec_type, width = 0, height = 0, sample_rate = 0, channels = 0; int stream_index = -1; -AVRational fps; +AVRational tb = av_make_q(0, 1); read_var_byte(s, &type); read_var_byte(s, &ssize); @@ -195,6 +195,7 @@ static int moflex_read_sync(AVFormatContext *s) return AVERROR_PATCHWELCOME; } sample_rate = avio_rb24(pb) + 1; +tb = av_make_q(1, sample_rate); channels = avio_r8(pb) + 1; break; case 1: @@ -208,8 +209,8 @@ static int moflex_read_sync(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "Unsupported video codec: %d\n", codec_id); return AVERROR_PATCHWELCOME; } -fps.num = avio_rb16(pb); -fps.den = avio_rb16(pb); +tb.den = avio_rb16(pb); +tb.num = avio_rb16(pb); width = avio_rb16(pb); height = avio_rb16(pb); avio_skip(pb, type == 3 ? 3 : 2); @@ -237,10 +238,8 @@ static int moflex_read_sync(AVFormatContext *s) if (!st->priv_data) return AVERROR(ENOMEM); -if (sample_rate) -avpriv_set_pts_info(st, 63, 1, sample_rate); -else -avpriv_set_pts_info(st, 63, fps.den, fps.num); +if (tb.num) +avpriv_set_pts_info(st, 63, tb.num, tb.den); } } -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v6] lavc/hevcdec: Parse DOVI RPU NALs
From: Niklas Haas Oops. The previous version of this patch forgot to actually forward the dovi configuration record to the DOVIContext. --- And expose the parsed values as frame side data. Update FATE results to match. It's worth documenting that this relies on the dovi configuration record being present on the first AVPacket fed to the decoder, which in practice is the case if if the API user has called something like av_format_inject_global_side_data, which is unfortunately not the default. This commit is not the time and place to change that behavior, though. Signed-off-by: Niklas Haas --- configure | 2 +- libavcodec/hevcdec.c | 63 +-- libavcodec/hevcdec.h | 3 + tests/ref/fate/hevc-dv-rpu | 224 + 4 files changed, 283 insertions(+), 9 deletions(-) diff --git a/configure b/configure index b8c9c5d2ae..d4336d20f5 100755 --- a/configure +++ b/configure @@ -2813,7 +2813,7 @@ h264_decoder_suggest="error_resilience" hap_decoder_select="snappy texturedsp" hap_encoder_deps="libsnappy" hap_encoder_select="texturedspenc" -hevc_decoder_select="atsc_a53 bswapdsp cabac golomb hevcparse videodsp" +hevc_decoder_select="atsc_a53 bswapdsp cabac dovi_rpu golomb hevcparse videodsp" huffyuv_decoder_select="bswapdsp huffyuvdsp llviddsp" huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp llvidencdsp" hymt_decoder_select="huffyuv_decoder" diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 46d9edf8eb..9ca2fa224d 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2723,6 +2723,7 @@ error: static int set_side_data(HEVCContext *s) { AVFrame *out = s->ref->frame; +int ret; if (s->sei.frame_packing.present && s->sei.frame_packing.arrangement_type >= 3 && @@ -2967,6 +2968,9 @@ static int set_side_data(HEVCContext *s) s->rpu_buf = NULL; } +if ((ret = ff_dovi_attach_side_data(&s->dovi_ctx, out)) < 0) +return ret; + return 0; } @@ -3298,16 +3302,24 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) if (s->pkt.nb_nals > 1 && s->pkt.nals[s->pkt.nb_nals - 1].type == HEVC_NAL_UNSPEC62 && s->pkt.nals[s->pkt.nb_nals - 1].size > 2 && !s->pkt.nals[s->pkt.nb_nals - 1].nuh_layer_id && !s->pkt.nals[s->pkt.nb_nals - 1].temporal_id) { +H2645NAL *nal = &s->pkt.nals[s->pkt.nb_nals - 1]; if (s->rpu_buf) { av_buffer_unref(&s->rpu_buf); av_log(s->avctx, AV_LOG_WARNING, "Multiple Dolby Vision RPUs found in one AU. Skipping previous.\n"); } -s->rpu_buf = av_buffer_alloc(s->pkt.nals[s->pkt.nb_nals - 1].raw_size - 2); +s->rpu_buf = av_buffer_alloc(nal->raw_size - 2); if (!s->rpu_buf) return AVERROR(ENOMEM); +memcpy(s->rpu_buf->data, nal->raw_data + 2, nal->raw_size - 2); -memcpy(s->rpu_buf->data, s->pkt.nals[s->pkt.nb_nals - 1].raw_data + 2, s->pkt.nals[s->pkt.nb_nals - 1].raw_size - 2); +s->dovi_ctx.config = s->dovi_cfg ? (void *) s->dovi_cfg->data : NULL; +ret = ff_dovi_rpu_parse(&s->dovi_ctx, nal->data + 2, nal->size - 2); +if (ret < 0) { +av_buffer_unref(&s->rpu_buf); +av_log(s->avctx, AV_LOG_WARNING, "Error parsing DOVI NAL unit.\n"); +/* ignore */ +} } /* decode the NAL units */ @@ -3440,8 +3452,8 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, AVPacket *avpkt) { int ret; -size_t new_extradata_size; -uint8_t *new_extradata; +uint8_t *sd; +size_t sd_size; HEVCContext *s = avctx->priv_data; if (!avpkt->size) { @@ -3453,14 +3465,37 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, return 0; } -new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, -&new_extradata_size); -if (new_extradata && new_extradata_size > 0) { -ret = hevc_decode_extradata(s, new_extradata, new_extradata_size, 0); +sd = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &sd_size); +if (sd && sd_size > 0) { +ret = hevc_decode_extradata(s, sd, sd_size, 0); if (ret < 0) return ret; } +sd = av_packet_get_side_data(avpkt, AV_PKT_DATA_DOVI_CONF, &sd_size); +if (sd && sd_size > 0) { +if (s->dovi_cfg) { +/* Reuse existing buffer */ +if ((ret = av_buffer_make_writable(&s->dovi_cfg)) < 0) +return ret; +} else { +/* Allocate new buffer */ +AVDOVIDecoderConfigurationRecord *cfg; +size_t cfg_size; +cfg = av_dovi_alloc(&cfg_size); +if (!cfg) +return AVERROR(ENOMEM); +s->dovi_cfg = av_buffer_create((uint8_t *) cfg, cfg_size, NULL, NULL, 0); +
Re: [FFmpeg-devel] Politics
> Far from it. I have pointed the core flaws with the design a few times, > but having been received with rudeness, I did not bother insisting. This > patch series is nowhere near anything that can be accepted. > This quickly went from exciting to depressing. :( I guess some recent-times archeology will also be needed in order to discuss this, as the patchset is 23 versions now and has 21 parts. I'll give it some time starting from tomorrow. If you Mr. George happen to remember where to look at, please kindly point me in the right direction, in order to avoid reading the full patchset history of messages. Of course, I'll read the whole thing otherwise, no problem. Also, from your last comment, I feel you're kinda pissed off with this patchset (or with softworkz, obviously). Yet, I've seen several answers from you years ago (like, about a decade now) where you were actually involved in the whole "subtitles in lavfi" thing. I mean: I've searched for this several times from years by now, and most of the time you were involved in the debates. I would say then this is something you care and have some knowledge about. If I were doing all the work softworkz is doing, I'll be pissed off with the backslash, no doubt about it. And if I were dealing with this use case for the last 10 years and people keep not doing what I'm convinced should be done, I'll be very pissed off too. So, this is kinda understandable. But I find it to be a pity that this use cases get blocked by people just not getting along. There has to be some way around it. Isn't there anything that can be done to combine both your knowledge and softworkz's will to tackle the issue? Perhaps laying down some base design that should be honored, while other people like softworkz or I could just progressively implement it? I bet that if softworkz code actually do the job, then it can't be THAT far away from an acceptable design, and thus that distance should be workable. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] Politics
Daniel Cantarín (12021-12-12): > This quickly went from exciting to depressing. :( I find this whole situation depressing too. > I guess some recent-times archeology will also be needed in order to > discuss this, as the patchset is 23 versions now and has 21 parts. I'll give > it some time starting from tomorrow. If you Mr. George happen to > remember where to look at, please kindly point me in the right direction, > in order to avoid reading the full patchset history of messages. Of > course, I'll read the whole thing otherwise, no problem. > > Also, from your last comment, I feel you're kinda pissed off with this > patchset (or with softworkz, obviously). Yet, I've seen several answers > from you years ago (like, about a decade now) where you were actually > involved in the whole "subtitles in lavfi" thing. I mean: I've searched for > this several times from years by now, and most of the time you were > involved in the debates. I would say then this is something you care > and have some knowledge about. > > If I were doing all the work softworkz is doing, I'll be pissed off with the > backslash, no doubt about it. And if I were dealing with this use case for > the last 10 years and people keep not doing what I'm convinced should > be done, I'll be very pissed off too. So, this is kinda understandable. > But I find it to be a pity that this use cases get blocked by people just > not getting along. There has to be some way around it. > > Isn't there anything that can be done to combine both your knowledge > and softworkz's will to tackle the issue? Perhaps laying down some base > design that should be honored, while other people like softworkz or I > could just progressively implement it? I have told Soft Works they were going at it the wrong way when they posted the very first patch. At the time, I was working on refactoring that needs to happen before libavfilter can be extended with a third media type. I gave Soft Works advice on how to help for tasks that are necessary to implement subtitles the right way. Instead of listening to my expertise, they persisted. If they wasted six months of effort and counting, they can blame only themselves. I still intend to work on this, I have clear plans on how to go forward, but right now I find the whole mess too depressing to even consider investing time in it. > I bet that if softworkz code actually do the job, then it can't be THAT far > away from an acceptable design, and thus that distance should be > workable. Unfortunately, it is that far. They designed and tested their patches with file inputs and simple grpahs. We need libavfilter to work with complex graphs where timestamps are changed, frames arrive in the wrong order on filters, etc. More importantly, they completely bypassed the format negotiation system, letting the responsibility fall onto users and making it impossible to have the many necessary utility filters without unacceptable code duplication. Regards, -- Nicolas George signature.asc Description: PGP signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] Politics
Hi, On Sun, Dec 12, 2021 at 1:21 PM Nicolas George wrote: > I have told Soft Works they were going at it the wrong way when they > posted the very first patch > There is no one magic correct way to do it. People work on things differently, and that's OK. Now, if there's issues with his approach, that's fine. But your argument here that you would've done it differently is not fair as a reason to reject the patch set. (No opinion on the patch set itself.) Ronald ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 000/279] New channel layout API
Quoting Marton Balint (2021-12-10 01:04:57) > > > On Thu, 9 Dec 2021, Anton Khirnov wrote: > > > Quoting Nicolas George (2021-12-09 11:31:54) > >> Anton Khirnov (12021-12-09): > >>> I disagree. Technical limitations that were overcome 10 years ago should > >>> not guide new API design. > >> > >> In the case of amerge, it was not a technical limitation, merging > >> several streams into one so that they can be handled by single-stream > >> filters is 100% part of the design. > > > > I fail to see how that is an advantage. You can just as well create > > multiple instances of those single-stream filters instead of adding > > hacks into core APIs. > > > >> I suspect devices that capture several independent channels are > >> designed that way intentionally too, possibly to reduce the risk of > >> desynchronization. > > > > "possibly" is not a strong enough argument. I'd like to hear at least > > one clearly-defined use case that cannot just as well be handled by > > using multiple streams. > > I recently worked on the MXF demuxer to recognize channel designations in > MXF files, and in MXF the designation and grouping of the channels is > completely separate from the track those channels are muxed in. > > So if you have e.g. english stereo sound, and german stereo sound you > can mux it > - as a single 4 channel track > - as two 2 channel tracks > - as four 1 channel tracks. > Some MXF flavors use the multichannel single track approach, others the > mono-track-only approach. So the user may not be able to choose the > optimal muxed track assignment... > > So ultimately, if you demux and decode a packet from a track, you will > have an AVFrame, which might contain a single sound group on its own > (optimal case), part of a sound group, or multiple sound groups. > > To summerize, muxed tracks are not necessarily 1:1 mapping between sound > groups. And when processing/filtering audio, you typically want sound > groups, not tracks. And yes, it is very rare to have a soundgroup which > has channels with the same designation, but for a muxed track, it depends > on the format. > > The goal of the end user is probably to be able to specify sound groups, > not select muxed tracks. Preferably a demuxer should provide which channel > is part of which sound group, and you should be able to use a filter or a > combination of filters select a specific sound group. E.g. amerge all > tracks, then keep only the channels from all the merged channels which are > part of a specific sound group. So what are you proposing? In my view, such higher level information should live at a higher level - e.g. in the side data. You can then have a filter that reads this side data and gets you the group you want. -- Anton Khirnov ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] Politics
Ronald S. Bultje (12021-12-12): > There is no one magic correct way to do it. People work on things > differently, and that's OK. There are wrong ways to do it. > Now, if there's issues with his approach, that's fine. There are many issues, I pointed them at the time and was rudely ignored. -- Nicolas George signature.asc Description: PGP signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 000/279] New channel layout API
Anton Khirnov (12021-12-12): > So what are you proposing? In my view, such higher level information > should live at a higher level - e.g. in the side data. You can then > have a filter that reads this side data and gets you the group you want. So, what is the point of this new API if anything of value needs to be done with side data and yet another API? It seems to me you are indulging in a sunken-costs fallacy: you wrote this API and all the code but you neglected to poll your fellow developers for needs that it should cover, and as a result got something much too limited. But now, you are trying to force it anyway. What I propose is: (1) define the needs properly; (2) redesign the API; (3) see how much code can still be used. The needs as far as I can see, please add to the list: A. Allow the same channel to appear several time in the layout. Hendrik agreed that it was useful for some kind of USER_SPECIFIED or UNKNOWN channel specification, but allowing for any channel specification is actually simpler. It is not limited to just having the same channel in the list, it requires API and user interface support: the API must be able to tell the user "this USER_SPECIFIED channel is the oboe, this USER_SPECIFIED is the piano", and the user must be able to tell the API "the second USER_SPECIFIED channel" or "the USER_SPECIFIED channel relating to the piano". B. Possibly, I do not personally insist on it like A: groups of channels. -- Nicolas George signature.asc Description: PGP signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] Politics
> -Original Message- > From: ffmpeg-devel On Behalf Of Soft Works > Sent: Sunday, December 12, 2021 7:16 AM > To: FFmpeg development discussions and patches > Subject: [FFmpeg-devel] Politics Hi, let me clarify a bit on the status and the motivation. I have started this development, because I needed the functionality. The decision - which retrospectively turned out to be stupid and non-rewarding - to do it in a way that it could also be merged into official ffmpeg has always been secondary. Nonetheless I have followed all suggestions (which were specific and constructive) to match everybody's expectation. At this point the development cycle for thy has come to an end. I have achieved all the goals I had and all things are working as expected without regressions in existing functionality. I find it offending when some developers which have followed my patchset over time and have even given earlier advice are approaching me now at the end and at the 23rd versions with ideas that would require going back and starting over to a large part or changing things that would endanger stability and require an enormous amount of work to get to the same degree of stability again. My response to that is: Sorry - you could have come earlier, but the window for such changes has closed long ago. (Nicolas, no need to respond, it's not about you) So what's the status? My patchset is an offering to ffmpeg - nothing more, nothing less. At this point, I am ready to do: - Small corrections or adjustments to satisfy requirements to get merged - Fixing all bugs and issues that get reported - Future updates, improvements and adding additional features and filter after merge As a benefit, this brings features and functionality to ffmpeg that have been lacking and highly requested for almost a decade. It's rather unlikely that a comparable submission will be made by anybody else in the next few years, even less likely from those who haven't managed to get going in that area for a long time. I understand that some developers are dissatisfied with the existence of the subtitle_pts field in the AVFrame struct. But it is a requirement for my patchset to work and I will not change it. Not because I don't want, but because it doesn't work without it. Not that I hadn't tried, but it remains the grain of salt that can't be avoided. So I think it burns down to the following: Everybody will need build his own opinion and decision about which of these things will outweigh the other: An undesired field in the AVFrame struct vs. a whole range of new functionality added to ffmpeg. (of course in addition to all other decision criteria every body will find important to consider). Maybe it's possible to put this up for a vote? If there's a majority against it, then it will be fine for me. It would just be great to find out better sooner than later, because then I could stop wasting my time on this. Kind regards, softworkz ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] Politics
On Sun, Dec 12, 2021 at 8:42 PM Nicolas George wrote: > Ronald S. Bultje (12021-12-12): > > There is no one magic correct way to do it. People work on things > > differently, and that's OK. > > There are wrong ways to do it. And there is only one path dictated by you. > > > Now, if there's issues with his approach, that's fine. > > There are many issues, I pointed them at the time and was rudely > ignored. > Lie. > > -- > Nicolas George > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v2] lavfi/drawtext: Add localtime_ms for millisecond precision
Thilo Borgman (12021-12-12): > +@item localtime_ms > +Same as @code{localtime} but with millisecond precision. > +It can accept an argument: a strftime() format string. What happens if the format string is something like '%H:%M:%S%z'? My guess it it prints 21:12:42+0100.1234 instead of 21:12:42.1234+0100. Regards, -- Nicolas George signature.asc Description: PGP signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] Politics
> -Original Message- > From: ffmpeg-devel On Behalf Of Paul B > Mahol > Sent: Sunday, December 12, 2021 9:09 PM > To: FFmpeg development discussions and patches > Subject: Re: [FFmpeg-devel] Politics > > On Sun, Dec 12, 2021 at 8:42 PM Nicolas George wrote: > > > Ronald S. Bultje (12021-12-12): > > > There is no one magic correct way to do it. People work on things > > > differently, and that's OK. > > > > There are wrong ways to do it. > > > And there is only one path dictated by you. > > > > > > > Now, if there's issues with his approach, that's fine. > > > > There are many issues, I pointed them at the time and was rudely > > ignored. > > > > Lie. It's in fact a plain lie because he never mentioned any technical and specific reason for objection. softworkz ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v20 02/20] avutil/frame: Prepare AVFrame\n for subtitle handling
On Sun, Dec 12, 2021 at 02:21:42AM +, Soft Works wrote: > > > > -Original Message- > > From: ffmpeg-devel On Behalf Of Daniel > > Cantarín > > Sent: Sunday, December 12, 2021 12:39 AM > > To: ffmpeg-devel@ffmpeg.org > > Subject: Re: [FFmpeg-devel] [PATCH v20 02/20] avutil/frame: Prepare > > AVFrame\n > > for subtitle handling > > > > > One of the important points to understand is that - in case of subtitles, > > > the AVFrame IS NOT the subtitle event. The subtitle event is actually > > > a different and separate entity. (...) > > > > > > Wouldn't it qualify then as a different abstraction? > > > > I mean: instead of avframe.subtitle_property, perhaps something in the > > lines of avframe.some_property_used_for_linked_abstractions, which in > > turn lets you access some proper Subtitle abstraction instance. > > > > That way, devs would not need to defend AVFrame, and Subtitle could > > have whatever properties needed. > > > > I see there's AVSubtitle, as you mention: > > https://ffmpeg.org/doxygen/trunk/structAVSubtitle.html > > > > Isn't it less socially problematic to just link an instance of AVSubtitle, > > instead of adding a subtitle timing property to AVFrame? > > IIUC, that AVSubtitle instance could live in filter context, and be linked > > by the filter doing the heartbeat frames. > > > > Please note I'm not saying the property is wrong, or even that I understand > > the best way to deal with it, but that I recognize some social problem here. > > Devs don't like that property, that's a fact. And technical or not, seems to > > be a problem. > > > > > (...) > > > The chairs are obviously AVFrames. They need to be numbered monotonically > > > increasing - that's the frame.pts. without increasing numbering the > > > transport would get stuck. We are filling the chairs with copies > > > of the most recent subtitle event, so an AVSubtitle could be repeated > > > like for example 5 times. It's always the exact same AVSubtitle event > > > sitting in those 5 chairs. The subtitle event has always the same > > start time > > > (subtitle_pts) but each frame has a different pts. > > > > I can see AVSubtitle has a "start_display_time" property, as well as a > > "pts" property "in AV_TIME_BASE": > > > > https://ffmpeg.org/doxygen/trunk/structAVSubtitle.html#af7cc390bba4f9d6c32e39 > > 1ca59d117a2 > > > > Is it too much trouble to reuse that while persisting an AVSubtitle instance > > in filter context? I guess it could even be used in decoder context. > > > > I also see a quirky property in AVFrame: "best_effort_timestamp" > > https://ffmpeg.org/doxygen/trunk/structAVFrame.html#a0943e85eb624c2191490862e > > cecd319d > > Perhaps adding there some added "various heuristics" that it claims to > > have, > > this time related to a linked AVSubtitle, so an extra property is not > > needed? > > > > > > > (...) > > > Considering the relation between AVFrame and subtitle event as laid out > > > above, it should be apparent that there's no guarantee for a certain > > > kind of relation between the subtitle_pts and the frame's pts who > > > is carrying it. Such relation _can_ exist, but doesn't necessarily. > > > It can easily be possible that the frame pts is just increased by 1 > > > on subsequent frames. The time_base may change from filter to filter > > > and can be oriented on the transport of the subtitle events which > > > might have nothing to do with the subtitle display time at all. > > > > This confuses me. > > I understand the difference between filler frame pts and subtitle pts. > > That's ok. > > But if transport timebase changes, I understand subtitle pts also changes. > > > > I mean: "transport timebase" means "video timebase", and if subs are synced > > to video, then that sync needs to be mantained. If subs are synced, then > > their timing is never independant. And if they're not synced, then its > > AVFrame > > is independant from video frames, and thus does not need any extra prop. > > > > Here's what I do right now with the filler frames. I'm talking about current > > ffmpeg with no subs frames in lavfi, and real-time conversion from dvbsub > > to WEBVTT using OCR. Quite dirty stuff what I do: > > - Change FPS to a low value, let's say 1. > > - Apply OCR to dvb sub, using vf_ocr. > > - Read the metadata downstream, and writting vtt to file or pipe output. > > > > As there's no sub frame capability in lavfi, I can't use vtt encoder > > downstream. > > Therefore, the output is raw C string and file manipulation. And given > > that I > > set first the FPS to 1, I have 1 line per second, no matter the > > timestamp of > > either subs or video or filler frame. The point then is to check for > > text diffs > > instead of pts for detecting the frame nature. And I can even naively > > just put > > the frame's pts once per sec with the same text, and with empty lines when > > there's no text, without caring about the frame nature (filler or not). >
Re: [FFmpeg-devel] [PATCH v20 02/20] avutil/frame: Prepare AVFrame\n for subtitle handling
On Sat, Dec 11, 2021 at 06:03:39PM +, Soft Works wrote: > > > > -Original Message- > > From: ffmpeg-devel On Behalf Of Michael > > Niedermayer > > Sent: Saturday, December 11, 2021 6:21 PM > > To: FFmpeg development discussions and patches > > Subject: Re: [FFmpeg-devel] [PATCH v20 02/20] avutil/frame: Prepare > > AVFrame\n > > for subtitle handling > > > > On Fri, Dec 10, 2021 at 03:02:32PM +, Soft Works wrote: > > > > > > > > > > -Original Message- > > > > From: ffmpeg-devel On Behalf Of Daniel > > > > Cantarín > > > > Sent: Thursday, December 9, 2021 10:33 PM > > > > To: ffmpeg-devel@ffmpeg.org > > > > Subject: Re: [FFmpeg-devel] [PATCH v20 02/20] avutil/frame: Prepare > > AVFrame\n > > > > for subtitle handling > > > > > > > > Hi there. > > > > This is my first message to this list, so please excuse me if I > > > > unintendedly break some rule. > > > > > > > > I've read the debate between Soft Works and others, and would like to > > > > add something to it. > > > > I don't have a deep knowledge of the libs as other people here show. My > > > > knowledge comes from working with live streams for some years now. And I > > > > do understand the issue about modifying a public API for some use case > > > > under debate: I believe it's a legit line of questioning to Soft Works > > > > patches. However, I also feel we live streaming people are often let > > > > aside as "border case" when it comes to ffmpeg/libav usage, and this > > > > bias is present in many subtitles/captions debates. > > > > > > > > I work with Digital TV signals as input, and several different target > > > > outputs more related to live streaming (mobiles, PCs, and so on). The > > > > target location is Latin America, and thus I need subtitles/captions for > > > > when we use english spoken audio (we speak mostly Spanish in LATAM). TV > > > > people send you TV subtitle formats: scte-27, dvb subs, and so on. And > > > > live streaming people uses other subtitles formats, mostly vtt and ttml. > > > > I've found that CEA-608 captions are the most compatible caption format, > > > > as it's understood natively by smart tvs and other devices, as well as > > > > non-natively by any other device using popular player-side libraries. > > > > So, I've made my own filter for generating CEA-608 captions for live > > > > streams, using ffmpeg with the previously available OCR filter. Tried > > > > VTT first, but it was problematic for live-streaming packaging, and with > > > > CEA-608 I could just ignore that part of the process. > > > > > > > > While doing those filters, besides the whole deal of implementing the > > > > conversion from text to CEA-608, I struggled with stuff like this: > > > > - the sparseness of input subtitles, leading to OOM in servers and > > > > stalled players. > > > > - the "libavfilter doesn't take subtitle frames" and "it's all ASS > > > > internally" issues. > > > > - the "captions timings vs video frame timings vs audio timings" > > > > problems (people talk a lot about syncing subs with video frames, but > > > > rarely against actual dialogue audio). > > > > - other (meta)data problems, like screen positioning or text encoding. > > > > > > > > This are all problems Soft Works seems to have faced as well. > > > > > > > > But of all the problems regarding live streaming subtitles with ffmpeg > > > > (and there are LOTS of it), the most annoying problem is always this: > > > > almost every time someone talked about implementing subtitles in filters > > > > (in mail lists, in tickets, in other places like stack overflow, > > > > etcetera), they always asumed input files. When the people specifically > > > > talked about live streams, their peers always reasoned with files > > > > mindset, and stated live streaming subtitles/captions as "border case". > > > > > > > > Let me be clear: this are not "border case" issues, but actually appear > > > > in the most common use cases of live streaming transcoding. They all > > > > appear *inmediatelly* when you try to use subtitles/captions in live > > > > streams. > > > > > > > > I got here (I mean this thread) while looking for ways to fixing some > > > > issues in my setup. I was reconsidering VTT/TTML generation instead of > > > > CEA-608 (as rendering behave significantly different from device to > > > > device), and thus I was about to generate subtitle type output from some > > > > filter, was about to create my own standalone "heartbeat" filter to > > > > normalize the sparseness, and so on and so on: again, all stuff Soft > > > > Works seems to be handling as well. So I was quite happy to find someone > > > > working on this again; last time I've seen it in ffmpeg's > > > > mailing/patchwork > > > > (https://patchwork.ffmpeg.org/project/ffmpeg/patch/20161102220934.26010- > > 1- > > > > u...@pkh.me) > > > > the code there seemed to die, and I was already late to say anything > > > > about it. However, reading the other devs reaction to Soft Works
Re: [FFmpeg-devel] [PATCH v3 1/2] swscale/x86/output.asm: add x86-optimized planer gbr yuv2anyX functions
On Wed, Nov 24, 2021 at 1:15 PM wrote: > From: Mark Reid > > changes since v2: > * fixed label > changes since v1: > * remove vex intruction on sse4 path > * some load/pack marcos use less intructions > * fixed some typos > > yuv2gbrp_full_X_4_512_c: 12757.6 > yuv2gbrp_full_X_4_512_sse2: 8946.6 > yuv2gbrp_full_X_4_512_sse4: 5138.6 > yuv2gbrp_full_X_4_512_avx2: 3889.6 > yuv2gbrap_full_X_4_512_c: 15368.6 > yuv2gbrap_full_X_4_512_sse2: 11916.1 > yuv2gbrap_full_X_4_512_sse4: 6294.6 > yuv2gbrap_full_X_4_512_avx2: 3477.1 > yuv2gbrp9be_full_X_4_512_c: 14381.6 > yuv2gbrp9be_full_X_4_512_sse2: 9139.1 > yuv2gbrp9be_full_X_4_512_sse4: 5150.1 > yuv2gbrp9be_full_X_4_512_avx2: 2834.6 > yuv2gbrp9le_full_X_4_512_c: 12990.1 > yuv2gbrp9le_full_X_4_512_sse2: 9118.1 > yuv2gbrp9le_full_X_4_512_sse4: 5132.1 > yuv2gbrp9le_full_X_4_512_avx2: 2833.1 > yuv2gbrp10be_full_X_4_512_c: 14401.6 > yuv2gbrp10be_full_X_4_512_sse2: 9133.1 > yuv2gbrp10be_full_X_4_512_sse4: 5126.1 > yuv2gbrp10be_full_X_4_512_avx2: 2837.6 > yuv2gbrp10le_full_X_4_512_c: 12718.1 > yuv2gbrp10le_full_X_4_512_sse2: 9106.1 > yuv2gbrp10le_full_X_4_512_sse4: 5120.1 > yuv2gbrp10le_full_X_4_512_avx2: 2826.1 > yuv2gbrap10be_full_X_4_512_c: 18535.6 > yuv2gbrap10be_full_X_4_512_sse2: 33617.6 > yuv2gbrap10be_full_X_4_512_sse4: 6264.1 > yuv2gbrap10be_full_X_4_512_avx2: 3422.1 > yuv2gbrap10le_full_X_4_512_c: 16724.1 > yuv2gbrap10le_full_X_4_512_sse2: 11787.1 > yuv2gbrap10le_full_X_4_512_sse4: 6282.1 > yuv2gbrap10le_full_X_4_512_avx2: 3441.6 > yuv2gbrp12be_full_X_4_512_c: 13723.6 > yuv2gbrp12be_full_X_4_512_sse2: 9128.1 > yuv2gbrp12be_full_X_4_512_sse4: 7997.6 > yuv2gbrp12be_full_X_4_512_avx2: 2844.1 > yuv2gbrp12le_full_X_4_512_c: 12257.1 > yuv2gbrp12le_full_X_4_512_sse2: 9107.6 > yuv2gbrp12le_full_X_4_512_sse4: 5142.6 > yuv2gbrp12le_full_X_4_512_avx2: 2837.6 > yuv2gbrap12be_full_X_4_512_c: 18511.1 > yuv2gbrap12be_full_X_4_512_sse2: 12156.6 > yuv2gbrap12be_full_X_4_512_sse4: 6251.1 > yuv2gbrap12be_full_X_4_512_avx2: 3444.6 > yuv2gbrap12le_full_X_4_512_c: 16687.1 > yuv2gbrap12le_full_X_4_512_sse2: 11785.1 > yuv2gbrap12le_full_X_4_512_sse4: 6243.6 > yuv2gbrap12le_full_X_4_512_avx2: 3446.1 > yuv2gbrp14be_full_X_4_512_c: 13690.6 > yuv2gbrp14be_full_X_4_512_sse2: 9120.6 > yuv2gbrp14be_full_X_4_512_sse4: 5138.1 > yuv2gbrp14be_full_X_4_512_avx2: 2843.1 > yuv2gbrp14le_full_X_4_512_c: 14995.6 > yuv2gbrp14le_full_X_4_512_sse2: 9119.1 > yuv2gbrp14le_full_X_4_512_sse4: 5126.1 > yuv2gbrp14le_full_X_4_512_avx2: 2843.1 > yuv2gbrp16be_full_X_4_512_c: 12367.1 > yuv2gbrp16be_full_X_4_512_sse2: 8233.6 > yuv2gbrp16be_full_X_4_512_sse4: 4820.1 > yuv2gbrp16be_full_X_4_512_avx2: 2666.6 > yuv2gbrp16le_full_X_4_512_c: 10904.1 > yuv2gbrp16le_full_X_4_512_sse2: 8214.1 > yuv2gbrp16le_full_X_4_512_sse4: 4824.1 > yuv2gbrp16le_full_X_4_512_avx2: 2629.1 > yuv2gbrap16be_full_X_4_512_c: 26569.6 > yuv2gbrap16be_full_X_4_512_sse2: 10884.1 > yuv2gbrap16be_full_X_4_512_sse4: 5488.1 > yuv2gbrap16be_full_X_4_512_avx2: 3272.1 > yuv2gbrap16le_full_X_4_512_c: 14010.1 > yuv2gbrap16le_full_X_4_512_sse2: 10562.1 > yuv2gbrap16le_full_X_4_512_sse4: 5463.6 > yuv2gbrap16le_full_X_4_512_avx2: 3255.1 > yuv2gbrpf32be_full_X_4_512_c: 14524.1 > yuv2gbrpf32be_full_X_4_512_sse2: 8552.6 > yuv2gbrpf32be_full_X_4_512_sse4: 4636.1 > yuv2gbrpf32be_full_X_4_512_avx2: 2474.6 > yuv2gbrpf32le_full_X_4_512_c: 13060.6 > yuv2gbrpf32le_full_X_4_512_sse2: 9682.6 > yuv2gbrpf32le_full_X_4_512_sse4: 4298.1 > yuv2gbrpf32le_full_X_4_512_avx2: 2453.1 > yuv2gbrapf32be_full_X_4_512_c: 18629.6 > yuv2gbrapf32be_full_X_4_512_sse2: 11363.1 > yuv2gbrapf32be_full_X_4_512_sse4: 15201.6 > yuv2gbrapf32be_full_X_4_512_avx2: 3727.1 > yuv2gbrapf32le_full_X_4_512_c: 16677.6 > yuv2gbrapf32le_full_X_4_512_sse2: 10221.6 > yuv2gbrapf32le_full_X_4_512_sse4: 5693.6 > yuv2gbrapf32le_full_X_4_512_avx2: 3656.6 > --- > libswscale/x86/output.asm | 434 +- > libswscale/x86/swscale.c | 98 + > tests/checkasm/Makefile | 2 +- > tests/checkasm/checkasm.c | 1 + > tests/checkasm/checkasm.h | 1 + > tests/checkasm/sw_gbrp.c | 198 + > tests/fate/checkasm.mak | 1 + > 7 files changed, 733 insertions(+), 2 deletions(-) > create mode 100644 tests/checkasm/sw_gbrp.c > > diff --git a/libswscale/x86/output.asm b/libswscale/x86/output.asm > index 52cf9f2c2e..e277a61449 100644 > --- a/libswscale/x86/output.asm > +++ b/libswscale/x86/output.asm > @@ -38,7 +38,49 @@ pw_32: times 8 dw 32 > pd_255:times 8 dd 255 > pw_512:times 8 dw 512 > pw_1024: times 8 dw 1024 > - > +pd_65535_invf: times 8 dd 0x37800080 ;1.0/65535.0 > +pd_yuv2gbrp16_start: times 8 dd -0x4000 > +pd_yuv2gbrp_y_start: times 8 dd (1 << 9) > +pd_yuv2gbrp_uv_start: times 8 dd ((1 << 9) - (128 << 19)) > +pd_yuv2gbrp_a_start: times 8 dd (1 << 18) > +pd_yuv2gbrp16_offset: times 8 dd 0x1 ;(1 << 16) > +pd_yuv2gbrp16_round13: times 8 dd 0x02000 ;(1 << 13) > +pd_yuv2g
Re: [FFmpeg-devel] [PATCH v3 0/5] Switch mmaldec to receive_frame API
It would definitely have to be an option. I tried lowering MAX_DELAYED_FRAMES myself. While it might work for live video streams, games streaming in your case, RTSP from CCTV cameras in mine, lower MAX_DELAYED_FRAMES seems to cause a decoding stall in any video with re-ordered frames. Thanks for testing this patchset! On Sun, Dec 12, 2021 at 9:09 AM Cameron Gutman wrote: > On 12/9/2021 7:01 AM, Andreas Rheinhardt wrote: > > This is an updated and extended version of [1] by Ho Ming Shun > > together with some additions by me. Notice that I am unable > > to test these patches (not even compilation), so I hope that > > others (Ho Ming Shun) do so. > > > > [1]: > https://ffmpeg.org/pipermail/ffmpeg-devel/2021-September/285992.html > > > > Andreas Rheinhardt (2): > >avcodec/mmaldec: Avoid creating unnecessary reference, simplify code > >avcodec/mmaldec: Deduplicate AVClasses > > > > Ho Ming Shun (3): > >avcodec/mmaldec: use decoupled dataflow > >avcodec/mmaldec: re-use AVPacket for extra_data > >avcodec/mmaldec: fix pointer type warning > > > > libavcodec/mmaldec.c | 81 +++- > > 1 file changed, 42 insertions(+), 39 deletions(-) > > > > This is fantastic work! I'm seeing significantly improved decode latency > here. I've been carrying an out-of-tree hack[0] for years to address the > extremely poor performance of mmaldec due to this async decoding behavior. > > The refactoring in this patch set _almost_ matches my dirty hack. > > With a realtime 60 FPS stream (so 1 packet per 16 ms) via Moonlight-Qt[1]: > - Current master: ~250 ms > - This patch set: ~18 ms > - My hack: ~14 ms > > With this patchset, I usually end up receiving frame N-1 when submitting > frame N. My hack manages to avoid asynchronous decoding altogether, so > I'm always receiving frame N after sending frame N for decoding. > > The absolute latency numbers are very close, but going over a frame of > latency is significant. The effective latency difference when it comes to > drawing the resulting image is 16 ms on a 60 Hz monitor due to V-sync. > > I assume my hack is unsuitable for inclusion in FFmpeg, but perhaps we > can figure out a way to avoid having to patch FFmpeg to get that behavior. > Maybe an AVOption to set MAX_DELAYED_FRAMES rather than hardcoding it? > > In any case, this is a _major_ improvement for my use so feel free to add > my Tested-by to this patch series: > > Tested-by: Cameron Gutman > > > > Regards, > Cam > > > [0]: > https://github.com/cgutman/FFmpeg/commit/193a0320afd5f316da407208eb2fdceea888ff64 > [1]: https://github.com/moonlight-stream/moonlight-qt > ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 1/7] avcodec/mpegvideo: Move closed_gop to Mpeg1Context
Only used there and only by the main thread. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpeg12dec.c | 8 +--- libavcodec/mpegvideo.c | 1 - libavcodec/mpegvideo.h | 1 - 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 09b2902bca..672031b6db 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -69,6 +69,7 @@ typedef struct Mpeg1Context { int rc_buffer_size; AVRational frame_rate_ext; /* MPEG-2 specific framerate modificator */ int sync; /* Did we reach a sync point like a GOP/SEQ/KEYFrame? */ +int closed_gop; int tmpgexs; int first_slice; int extradata_decoded; @@ -2449,7 +2450,7 @@ static void mpeg_decode_gop(AVCodecContext *avctx, tc = s-> timecode_frame_start = get_bits(&s->gb, 25); -s->closed_gop = get_bits1(&s->gb); +s1->closed_gop = get_bits1(&s->gb); /* broken_link indicates that after editing the * reference frames of the first B-Frames after GOP I-Frame * are missing (open gop) */ @@ -2460,7 +2461,7 @@ static void mpeg_decode_gop(AVCodecContext *avctx, av_timecode_make_mpeg_tc_string(tcbuf, tc); av_log(s->avctx, AV_LOG_DEBUG, "GOP (%s) closed_gop=%d broken_link=%d\n", - tcbuf, s->closed_gop, broken_link); + tcbuf, s1->closed_gop, broken_link); } } @@ -2694,7 +2695,7 @@ static int decode_chunks(AVCodecContext *avctx, AVFrame *picture, /* Skip B-frames if we do not have reference frames and * GOP is not closed. */ if (s2->pict_type == AV_PICTURE_TYPE_B) { -if (!s2->closed_gop) { +if (!s->closed_gop) { skip_frame = 1; av_log(s2->avctx, AV_LOG_DEBUG, "Skipping B slice due to open GOP\n"); @@ -2882,6 +2883,7 @@ static void flush(AVCodecContext *avctx) Mpeg1Context *s = avctx->priv_data; s->sync = 0; +s->closed_gop = 0; ff_mpeg_flush(avctx); } diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index ba5b51955e..55399a7478 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -2317,7 +2317,6 @@ void ff_mpeg_flush(AVCodecContext *avctx){ ff_mpeg_unref_picture(s->avctx, &s->next_picture); s->mb_x= s->mb_y= 0; -s->closed_gop= 0; #if FF_API_FLAG_TRUNCATED s->parse_context.state= -1; diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index e90669b776..85f02b1355 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -198,7 +198,6 @@ typedef struct MpegEncContext { int *lambda_table; int adaptive_quant; ///< use adaptive quantization int dquant; ///< qscale difference to prev qscale -int closed_gop; ///< MPEG1/2 GOP is closed int pict_type; ///< AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, ... int vbv_delay; int last_pict_type; //FIXME removes -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 2/7] avcodec/mpegvideo: Don't update encoder-only fields for decoders
ff_mpeg_update_thread_context() is only used by decoders. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 55399a7478..b5ff4cec69 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -658,12 +658,6 @@ do {\ memcpy(&s->progressive_sequence, &s1->progressive_sequence, (char *) &s1->rtp_mode - (char *) &s1->progressive_sequence); -if (!s1->first_field) { -s->last_pict_type = s1->pict_type; -if (s1->current_picture_ptr) -s->last_lambda_for[s1->pict_type] = s1->current_picture_ptr->f->quality; -} - return 0; } -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 3/7] avcodec/mpegvideo_end, vc1dec: Remove always-false check
Mpeg1EncContext.droppable is only nonzero for the FLV decoder. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo_enc.c | 3 +-- libavcodec/vc1dec.c| 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index f804b8215d..d33cf9477d 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1658,8 +1658,7 @@ static int frame_start(MpegEncContext *s) if (s->pict_type != AV_PICTURE_TYPE_B) { s->last_picture_ptr = s->next_picture_ptr; -if (!s->droppable) -s->next_picture_ptr = s->current_picture_ptr; +s->next_picture_ptr = s->current_picture_ptr; } if (s->last_picture_ptr) { diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index e636fa6160..267d72d15b 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -862,7 +862,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; /* skip B-frames if we don't have reference frames */ -if (!s->last_picture_ptr && (s->pict_type == AV_PICTURE_TYPE_B || s->droppable)) { +if (!s->last_picture_ptr && s->pict_type == AV_PICTURE_TYPE_B) { av_log(v->s.avctx, AV_LOG_DEBUG, "Skipping B frame without reference frames\n"); goto end; } -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 4/7] avcodec/mpegvideo: Don't allocate encoder-only buffers when decoding
Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 20 +++- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index b5ff4cec69..e2cdba8bb1 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -768,11 +768,9 @@ static int init_context_frame(MpegEncContext *s) !FF_ALLOC_TYPED_ARRAY (s->cplx_tab, mb_array_size) || !FF_ALLOC_TYPED_ARRAY (s->bits_tab, mb_array_size)) return AVERROR(ENOMEM); -} if (s->codec_id == AV_CODEC_ID_MPEG4 || (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { -/* interlaced direct mode decoding tables */ for (i = 0; i < 2; i++) { int j, k; for (j = 0; j < 2; j++) { @@ -782,15 +780,27 @@ static int init_context_frame(MpegEncContext *s) s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] + s->mb_stride + 1; } -if (!FF_ALLOCZ_TYPED_ARRAY(s->b_field_select_table [i][j], mv_table_size * 2) || -!FF_ALLOCZ_TYPED_ARRAY(s->p_field_mv_table_base[i][j], mv_table_size)) +if (!FF_ALLOCZ_TYPED_ARRAY(s->b_field_select_table [i][j], mv_table_size * 2)) return AVERROR(ENOMEM); -s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] + s->mb_stride + 1; } if (!FF_ALLOCZ_TYPED_ARRAY(s->p_field_select_table[i], mv_table_size * 2)) return AVERROR(ENOMEM); } } +} + +if (s->codec_id == AV_CODEC_ID_MPEG4 || +(s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { +/* interlaced direct mode decoding tables */ +for (int i = 0; i < 2; i++) { +for (int j = 0; j < 2; j++) { +if (!FF_ALLOCZ_TYPED_ARRAY(s->p_field_mv_table_base[i][j], mv_table_size)) +return AVERROR(ENOMEM); +s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] + s->mb_stride + 1; +} +} +} + if (s->out_format == FMT_H263) { /* cbp values, cbp, ac_pred, pred_dir */ if (!FF_ALLOCZ_TYPED_ARRAY(s->coded_block_base, y_size + (s->mb_height&1)*2*s->b8_stride) || -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 7/7] avcodec/mpegvideo: Reindentation
Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 15 +++ 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index be47ccb8ed..46e56ca08e 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -770,8 +770,8 @@ static int init_context_frame(MpegEncContext *s) return AVERROR(ENOMEM); #define ALLOCZ_ARRAYS(p, mult, numb) ((p) = av_calloc(numb, mult * sizeof(*(p -if (s->codec_id == AV_CODEC_ID_MPEG4 || -(s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { +if (s->codec_id == AV_CODEC_ID_MPEG4 || +(s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { int16_t (*tmp1)[2]; uint8_t *tmp2; if (!(tmp1 = ALLOCZ_ARRAYS(s->b_field_mv_table_base, 8, mv_table_size)) || @@ -782,19 +782,18 @@ static int init_context_frame(MpegEncContext *s) s->p_field_select_table[1] = s->p_field_select_table[0] + 2 * mv_table_size; tmp1 += s->mb_stride + 1; -for (i = 0; i < 2; i++) { -int j, k; -for (j = 0; j < 2; j++) { -for (k = 0; k < 2; k++) { +for (int i = 0; i < 2; i++) { +for (int j = 0; j < 2; j++) { +for (int k = 0; k < 2; k++) { s->b_field_mv_table[i][j][k] = tmp1; tmp1 += mv_table_size; -} +} s->b_field_select_table[i][j] = tmp2; tmp2 += 2 * mv_table_size; +} } } } -} if (s->codec_id == AV_CODEC_ID_MPEG4 || (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 6/7] avcodec/h263: Remove declaration of inexistent function
Forgotten in c46eeae2a80dfe0046c15b542e8b9a2c78f19bf7. Signed-off-by: Andreas Rheinhardt --- libavcodec/h263.h | 7 --- 1 file changed, 7 deletions(-) diff --git a/libavcodec/h263.h b/libavcodec/h263.h index d6bef8318d..84a3a19517 100644 --- a/libavcodec/h263.h +++ b/libavcodec/h263.h @@ -87,13 +87,6 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s); int ff_h263_decode_mb(MpegEncContext *s, int16_t block[6][64]); -/** - * Return the value of the 3-bit "source format" syntax element. - * This represents some standard picture dimensions or indicates that - * width&height are explicitly stored later. - */ -int av_const h263_get_picture_format(int width, int height); - void ff_clean_h263_qscales(MpegEncContext *s); int ff_h263_resync(MpegEncContext *s); void ff_h263_encode_motion(PutBitContext *pb, int val, int f_code); -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 5/7] avcodec/mpegvideo: Allocate several buffers jointly
Reduces the amount of allocations and frees. Signed-off-by: Andreas Rheinhardt --- libavcodec/mpegvideo.c | 46 ++ libavcodec/mpegvideo.h | 8 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index e2cdba8bb1..be47ccb8ed 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -769,34 +769,44 @@ static int init_context_frame(MpegEncContext *s) !FF_ALLOC_TYPED_ARRAY (s->bits_tab, mb_array_size)) return AVERROR(ENOMEM); +#define ALLOCZ_ARRAYS(p, mult, numb) ((p) = av_calloc(numb, mult * sizeof(*(p if (s->codec_id == AV_CODEC_ID_MPEG4 || (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { +int16_t (*tmp1)[2]; +uint8_t *tmp2; +if (!(tmp1 = ALLOCZ_ARRAYS(s->b_field_mv_table_base, 8, mv_table_size)) || +!(tmp2 = ALLOCZ_ARRAYS(s->b_field_select_table[0][0], 2 * 4, mv_table_size)) || +!ALLOCZ_ARRAYS(s->p_field_select_table[0], 2 * 2, mv_table_size)) +return AVERROR(ENOMEM); + +s->p_field_select_table[1] = s->p_field_select_table[0] + 2 * mv_table_size; +tmp1 += s->mb_stride + 1; + for (i = 0; i < 2; i++) { int j, k; for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { -if (!FF_ALLOCZ_TYPED_ARRAY(s->b_field_mv_table_base[i][j][k], mv_table_size)) -return AVERROR(ENOMEM); -s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] + - s->mb_stride + 1; +s->b_field_mv_table[i][j][k] = tmp1; +tmp1 += mv_table_size; } -if (!FF_ALLOCZ_TYPED_ARRAY(s->b_field_select_table [i][j], mv_table_size * 2)) -return AVERROR(ENOMEM); +s->b_field_select_table[i][j] = tmp2; +tmp2 += 2 * mv_table_size; } -if (!FF_ALLOCZ_TYPED_ARRAY(s->p_field_select_table[i], mv_table_size * 2)) -return AVERROR(ENOMEM); } } } if (s->codec_id == AV_CODEC_ID_MPEG4 || (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { +int16_t (*tmp)[2]; /* interlaced direct mode decoding tables */ +if (!(tmp = ALLOCZ_ARRAYS(s->p_field_mv_table_base, 4, mv_table_size))) +return AVERROR(ENOMEM); +tmp += s->mb_stride + 1; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { -if (!FF_ALLOCZ_TYPED_ARRAY(s->p_field_mv_table_base[i][j], mv_table_size)) -return AVERROR(ENOMEM); -s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] + s->mb_stride + 1; +s->p_field_mv_table[i][j] = tmp; +tmp += mv_table_size; } } } @@ -880,14 +890,14 @@ static void clear_context(MpegEncContext *s) s->b_bidir_forw_mv_table = NULL; s->b_bidir_back_mv_table = NULL; s->b_direct_mv_table = NULL; +s->b_field_mv_table_base = NULL; +s->p_field_mv_table_base = NULL; for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { -s->b_field_mv_table_base[i][j][k] = NULL; s->b_field_mv_table[i][j][k] = NULL; } s->b_field_select_table[i][j] = NULL; -s->p_field_mv_table_base[i][j] = NULL; s->p_field_mv_table[i][j] = NULL; } s->p_field_select_table[i] = NULL; @@ -1026,17 +1036,19 @@ static void free_context_frame(MpegEncContext *s) s->b_bidir_forw_mv_table = NULL; s->b_bidir_back_mv_table = NULL; s->b_direct_mv_table = NULL; +av_freep(&s->b_field_mv_table_base); +av_freep(&s->b_field_select_table[0][0]); +av_freep(&s->p_field_mv_table_base); +av_freep(&s->p_field_select_table[0]); for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { -av_freep(&s->b_field_mv_table_base[i][j][k]); s->b_field_mv_table[i][j][k] = NULL; } -av_freep(&s->b_field_select_table[i][j]); -av_freep(&s->p_field_mv_table_base[i][j]); +s->b_field_select_table[i][j] = NULL; s->p_field_mv_table[i][j] = NULL; } -av_freep(&s->p_field_select_table[i]); +s->p_field_select_table[i] = NULL; } av_freep(&s->dc_val_base); diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 85f02b1355..879b019ffc 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -232,8 +232,8 @@ typedef struct MpegEncContext { int16_t (*b_bidir_forw_mv_table_base)[2]; int16_t (*b_bidir_back_mv_table_base)[
Re: [FFmpeg-devel] [PATCH 1/5] avformat/movenc: remove unused argument from get_sample_flags()
Ping for patch 1-3. > On Dec 3, 2021, at 1:06 PM, Zhao Zhili wrote: > > --- > libavformat/movenc.c | 12 ++-- > 1 file changed, 6 insertions(+), 6 deletions(-) > > diff --git a/libavformat/movenc.c b/libavformat/movenc.c > index 38ff90833a..634a829f28 100644 > --- a/libavformat/movenc.c > +++ b/libavformat/movenc.c > @@ -4427,7 +4427,7 @@ static int mov_write_mfhd_tag(AVIOContext *pb, > MOVMuxContext *mov) > return 0; > } > > -static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry) > +static uint32_t get_sample_flags(MOVIentry *entry) > { > return entry->flags & MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO : >(MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | > MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC); > @@ -4487,7 +4487,7 @@ static int mov_write_tfhd_tag(AVIOContext *pb, > MOVMuxContext *mov, > /* Set the default flags based on the second sample, if available. > * If the first sample is different, that can be signaled via a > separate field. */ > if (track->entry > 1) > -track->default_sample_flags = get_sample_flags(track, > &track->cluster[1]); > +track->default_sample_flags = > get_sample_flags(&track->cluster[1]); > else > track->default_sample_flags = > track->par->codec_type == AVMEDIA_TYPE_VIDEO ? > @@ -4512,11 +4512,11 @@ static int mov_write_trun_tag(AVIOContext *pb, > MOVMuxContext *mov, > flags |= MOV_TRUN_SAMPLE_DURATION; > if (track->cluster[i].size != track->default_size) > flags |= MOV_TRUN_SAMPLE_SIZE; > -if (i > first && get_sample_flags(track, &track->cluster[i]) != > track->default_sample_flags) > +if (i > first && get_sample_flags(&track->cluster[i]) != > track->default_sample_flags) > flags |= MOV_TRUN_SAMPLE_FLAGS; > } > if (!(flags & MOV_TRUN_SAMPLE_FLAGS) && track->entry > 0 && > - get_sample_flags(track, &track->cluster[0]) != > track->default_sample_flags) > + get_sample_flags(&track->cluster[0]) != track->default_sample_flags) > flags |= MOV_TRUN_FIRST_SAMPLE_FLAGS; > if (track->flags & MOV_TRACK_CTTS) > flags |= MOV_TRUN_SAMPLE_CTS; > @@ -4538,7 +4538,7 @@ static int mov_write_trun_tag(AVIOContext *pb, > MOVMuxContext *mov, > avio_wb32(pb, moof_size + 8 + track->data_offset + > track->cluster[first].pos); /* data offset */ > if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) > -avio_wb32(pb, get_sample_flags(track, &track->cluster[first])); > +avio_wb32(pb, get_sample_flags(&track->cluster[first])); > > for (i = first; i < end; i++) { > if (flags & MOV_TRUN_SAMPLE_DURATION) > @@ -4546,7 +4546,7 @@ static int mov_write_trun_tag(AVIOContext *pb, > MOVMuxContext *mov, > if (flags & MOV_TRUN_SAMPLE_SIZE) > avio_wb32(pb, track->cluster[i].size); > if (flags & MOV_TRUN_SAMPLE_FLAGS) > -avio_wb32(pb, get_sample_flags(track, &track->cluster[i])); > +avio_wb32(pb, get_sample_flags(&track->cluster[i])); > if (flags & MOV_TRUN_SAMPLE_CTS) > avio_wb32(pb, track->cluster[i].cts); > } > -- > 2.31.1 > ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v9 1/2] avformat/imf: Demuxer
On 9/12/21 13:55, p...@sandflow.com wrote: + +#define FF_UUID_FORMAT\ +"urn:uuid:%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-" \ +"%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" + +/** + * UUID as defined in IETF RFC 422 + */ +typedef uint8_t FFUUID[16]; + Perhaps change to FF_IMF_UUID_FORMAT and FFIMFUUID, unless you intend these to be used for all of FFmpeg? I also agree with Lynne that we shouldn't ad-hoc UUIDs. libuuid is nice and wouldn't be too bad to add as a dependency. It'll also be handy if some other part needs to handle UUIDs in the future. Even though it might not support "urn:uuid:", you can just offset the pointer before giving it to uuid_parse (or uuid_parse_range). Alternatively, if all you need to do is compare them, could you not just compare the raw strings, skipping the parsing entirely? +/** + * Parse an IMF CompositionPlaylist element into the FFIMFCPL data structure. + * @param[in] doc An XML document from which the CPL is read. + * @param[out] cpl Pointer to a memory area (allocated by the client), where the + * function writes a pointer to the newly constructed FFIMFCPL structure (or + * NULL if the CPL could not be parsed). The client is responsible for freeing + * the FFIMFCPL structure using ff_imf_cpl_free(). + * @return A non-zero value in case of an error. + */ +int ff_parse_imf_cpl_from_xml_dom(xmlDocPtr doc, FFIMFCPL **cpl); + ff_imf_parse_cpl_from_xml_dom(), ff_parse_* is taken. Also for consistency with everything else. +/** + * Parse an IMF Composition Playlist document into the FFIMFCPL data structure. + * @param[in] in The context from which the CPL is read. + * @param[out] cpl Pointer to a memory area (allocated by the client), where the + * function writes a pointer to the newly constructed FFIMFCPL structure (or + * NULL if the CPL could not be parsed). The client is responsible for freeing + * the FFIMFCPL structure using ff_imf_cpl_free(). + * @return A non-zero value in case of an error. + */ +int ff_parse_imf_cpl(AVIOContext *in, FFIMFCPL **cpl); + Ditto. +/** + * Reads an unsigned 32-bit integer from an XML element + * @return 0 on success, < 0 AVERROR code on error. + */ +int ff_xml_read_uint32(xmlNodePtr element, uint32_t *number); + +/** + * Reads an AVRational from an XML element + * @return 0 on success, < 0 AVERROR code on error. + */ +int ff_xml_read_rational(xmlNodePtr element, AVRational *rational); + +/** + * Reads a UUID from an XML element + * @return 0 on success, < 0 AVERROR code on error. + */ +int ff_xml_read_uuid(xmlNodePtr element, uint8_t uuid[16]); + +/** + * Returns the first child element with the specified local name + * @return A pointer to the child element, or NULL if no such child element exists. + */ +xmlNodePtr ff_xml_get_child_element_by_name(xmlNodePtr parent, const char *name_utf8); + If these are only used for IMF, then ff_imf_xml_*(). Afaik FFmpeg doesn't have any centralised XML helpers (and perhaps it should, there's a few things that use libxml from a quick grep). + +const AVInputFormat ff_imf_demuxer = { +.name = "imf", +.long_name = NULL_IF_CONFIG_SMALL("IMF (Interoperable Master Format)"), +.flags_internal = FF_FMT_INIT_CLEANUP, +.priv_class = &imf_class, +.priv_data_size = sizeof(IMFContext), +.read_header= imf_read_header, +.read_packet= imf_read_packet, +.read_close = imf_close, +.extensions = "xml", I'm a bit apprehensive about this. This will unconditionally set all XML files as imf. How difficult would it be to add a probe function? +.mime_type = "application/xml,text/xml", +}; ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v10 1/2] avformat/imf: Demuxer
From: Pierre-Anthony Lemieux Signed-off-by: Pierre-Anthony Lemieux --- Notes: The IMF demuxer accepts as input an IMF CPL. The assets referenced by the CPL can be contained in multiple deliveries, each defined by an ASSETMAP file: ffmpeg -assetmaps ,,... -i If -assetmaps is not specified, FFMPEG looks for a file called ASSETMAP.xml in the same directory as the CPL. EXAMPLE: ffmpeg -i http://ffmpeg-imf-samples-public.s3-website-us-west-1.amazonaws.com/countdown/CPL_f5095caa-f204-4e1c-8a84-7af48c7ae16b.xml out.mp4 The Interoperable Master Format (IMF) is a file-based media format for the delivery and storage of professional audio-visual masters. An IMF Composition consists of an XML playlist (the Composition Playlist) and a collection of MXF files (the Track Files). The Composition Playlist (CPL) assembles the Track Files onto a timeline, which consists of multiple tracks. The location of the Track Files referenced by the Composition Playlist is stored in one or more XML documents called Asset Maps. More details at https://www.imfug.com/explainer. The IMF standard was first introduced in 2013 and is managed by the SMPTE. CHANGE NOTES: - add imf_probe - improve imf-specific function names MAINTAINERS | 1 + configure| 3 +- doc/demuxers.texi| 6 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/imf.h| 207 + libavformat/imf_cpl.c| 782 + libavformat/imfdec.c | 905 +++ 8 files changed, 1905 insertions(+), 1 deletion(-) create mode 100644 libavformat/imf.h create mode 100644 libavformat/imf_cpl.c create mode 100644 libavformat/imfdec.c diff --git a/MAINTAINERS b/MAINTAINERS index dcac46003e..7a6972fe1a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -433,6 +433,7 @@ Muxers/Demuxers: idroqdec.cMike Melanson iff.c Jaikrishnan Menon img2*.c Michael Niedermayer + imf*.cMarc-Antoine Arnaud, Pierre-Anthony Lemieux, Valentin Noël ipmovie.c Mike Melanson ircam*Paul B Mahol iss.c Stefan Gehrer diff --git a/configure b/configure index a7593ec2db..aa8bae4d62 100755 --- a/configure +++ b/configure @@ -298,7 +298,7 @@ External library support: --enable-libxvid enable Xvid encoding via xvidcore, native MPEG-4/Xvid encoder exists [no] --enable-libxml2 enable XML parsing using the C library libxml2, needed - for dash demuxing support [no] + for dash and imf demuxing support [no] --enable-libzimg enable z.lib, needed for zscale filter [no] --enable-libzmq enable message passing via libzmq [no] --enable-libzvbi enable teletext support via libzvbi [no] @@ -3400,6 +3400,7 @@ hls_muxer_select="mpegts_muxer" hls_muxer_suggest="gcrypt openssl" image2_alias_pix_demuxer_select="image2_demuxer" image2_brender_pix_demuxer_select="image2_demuxer" +imf_demuxer_deps="libxml2" ipod_muxer_select="mov_muxer" ismv_muxer_select="mov_muxer" ivf_muxer_select="av1_metadata_bsf vp9_superframe_bsf" diff --git a/doc/demuxers.texi b/doc/demuxers.texi index cab8a7072c..655704d2c4 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -267,6 +267,12 @@ which streams to actually receive. Each stream mirrors the @code{id} and @code{bandwidth} properties from the @code{} as metadata keys named "id" and "variant_bitrate" respectively. +@section imf + +Interoperable Master Format demuxer. + +This demuxer presents audio and video streams found in an IMF Composition. + @section flv, live_flv, kux Adobe Flash Video Format demuxer. diff --git a/libavformat/Makefile b/libavformat/Makefile index 2b5caf9d33..7f058f3ea0 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -285,6 +285,7 @@ OBJS-$(CONFIG_IMAGE_WEBP_PIPE_DEMUXER)+= img2dec.o img2.o OBJS-$(CONFIG_IMAGE_XBM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_XPM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_XWD_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMF_DEMUXER) += imfdec.o imf_cpl.o OBJS-$(CONFIG_INGENIENT_DEMUXER) += ingenientdec.o rawdec.o OBJS-$(CONFIG_IPMOVIE_DEMUXER) += ipmovie.o OBJS-$(CONFIG_IPU_DEMUXER) += ipudec.o rawdec.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 1054ac9667..f680616cdd 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -212,6 +212,7 @@ extern const AVInputFormat ff_image2pipe_demuxer; extern const AVOutputFormat ff_image2pipe_muxer; extern const AVInputFormat ff_i
[FFmpeg-devel] [PATCH v10 2/2] avformat/imf: Tests
From: Pierre-Anthony Lemieux Signed-off-by: Pierre-Anthony Lemieux --- Notes: Tests for the IMF demuxer. libavformat/Makefile| 1 + libavformat/tests/imf.c | 525 2 files changed, 526 insertions(+) create mode 100644 libavformat/tests/imf.c diff --git a/libavformat/Makefile b/libavformat/Makefile index 7f058f3ea0..533bb67f31 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -697,6 +697,7 @@ TESTPROGS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh TESTPROGS-$(CONFIG_MOV_MUXER)+= movenc TESTPROGS-$(CONFIG_NETWORK) += noproxy TESTPROGS-$(CONFIG_SRTP) += srtp +TESTPROGS-$(CONFIG_IMF_DEMUXER) += imf TOOLS = aviocat \ ismindex\ diff --git a/libavformat/tests/imf.c b/libavformat/tests/imf.c new file mode 100644 index 00..f163886ba8 --- /dev/null +++ b/libavformat/tests/imf.c @@ -0,0 +1,525 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * + * Copyright (c) Sandflow Consulting LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Tests for IMF CPL and ASSETMAP processing + * + * @author Valentin Noel + * @author Pierre-Anthony Lemieux + * @file + * @ingroup lavu_imf + */ + +#include "libavformat/imf_cpl.c" +#include "libavformat/imfdec.c" +#include "libavformat/mxf.h" + +#include + +const char *cpl_doc = +"http://www.smpte-ra.org/schemas/2067-3/2016\""; +" xmlns:cc=\"http://www.smpte-ra.org/schemas/2067-2/2016\""; +" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\";>" +"urn:uuid:8713c020-2489-45f5-a9f7-87be539e20b5" +"2021-07-13T17:06:22Z" +"FFMPEG" +"FFMPEG sample content" +"" +" " +"urn:uuid:8e097bb0-cff7-4969-a692-bad47bfb528f" +" " +"" +"24000 1001" +"" +"" +"urn:uuid:81fed4e5-9722-400a-b9d1-7f2bd21df4b6" +"" +"" +"urn:uuid:16327185-9205-47ef-a17b-ee28df251db7" +"urn:uuid:461f5424-8f6e-48a9-a385-5eda46fda381" +"" +"" +"urn:uuid:ea3d0f23-55d6-4e03-86ec-cfe0666f0e6a" +"24" +"" +"LFOA" +"5" +"" +"" +"" +"" +"" +"urn:uuid:6ae100b0-92d1-41be-9321-85e0933dfc42" +"urn:uuid:e8ef9653-565c-479c-8039-82d4547973c5" +"" +"" +"urn:uuid:7d418acb-07a3-4e57-984c-b8ea2f7de4ec" +"24" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" +"urn:uuid:6f768ca4-c89e-4dac-9056-a29425d40ba1" +"" +"" +"" +"" +"urn:uuid:754dae53-c25f-4f3c-97e4-2bfe5463f83b" +"urn:uuid:68e3fae5-d94b-44d2-92a6-b94877fbcdb5" +"" +"" +"urn:uuid:61ce2a70-10a2-4521-850b-4218755ff3c9" +"24" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" +"urn:uuid:381dadd2-061e-46cc-a63a-e3d58ce7f488" +"" +"" +"" +"" +"urn:uuid:d29b3884-6633-4dad-9c67-7154af342bc6" +"urn:uuid:6978c106-95bc-424b-a17
Re: [FFmpeg-devel] [PATCH v3 2/2] avcodec/vpp_qsv: Copy side data from input to output frame
> > -Original Message- > > From: ffmpeg-devel On Behalf Of Xiang, > > Haihao > > Sent: Thursday, December 9, 2021 9:35 AM > > To: ffmpeg-devel@ffmpeg.org > > Subject: Re: [FFmpeg-devel] [PATCH v3 2/2] avcodec/vpp_qsv: Copy side data > > from input to output frame > > > > On Tue, 2021-12-07 at 12:39 +, Soft Works wrote: > > > > -Original Message- > > > > From: ffmpeg-devel On Behalf Of Anton > > > > Khirnov > > > > Sent: Tuesday, December 7, 2021 12:51 PM > > > > To: FFmpeg development discussions and patches > > > > Subject: Re: [FFmpeg-devel] [PATCH v3 2/2] avcodec/vpp_qsv: Copy side > > > > data > > > > from input to output frame > > > > > > > > Quoting Soft Works (2021-12-07 09:55:37) > > > > > > > > > > > > > > > > -Original Message- > > > > > > From: ffmpeg-devel On Behalf Of > > > > Anton > > > > > > Khirnov > > > > > > Sent: Tuesday, December 7, 2021 9:04 AM > > > > > > To: ffmpeg-devel@ffmpeg.org > > > > > > Subject: Re: [FFmpeg-devel] [PATCH v3 2/2] avcodec/vpp_qsv: Copy > > > > > > side > > > > > > > > data > > > > > > from input to output frame > > > > > > > > > > > > Quoting Soft Works (2021-12-03 08:58:31) > > > > > > > Signed-off-by: softworkz > > > > > > > --- > > > > > > > libavfilter/qsvvpp.c | 5 + > > > > > > > libavfilter/vf_overlay_qsv.c | 19 +++ > > > > > > > 2 files changed, 20 insertions(+), 4 deletions(-) > > > > > > > > > > > > > > diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c > > > > > > > index d1218355c7..b291216292 100644 > > > > > > > --- a/libavfilter/qsvvpp.c > > > > > > > +++ b/libavfilter/qsvvpp.c > > > > > > > @@ -849,6 +849,11 @@ int ff_qsvvpp_filter_frame(QSVVPPContext *s, > > > > > > > > > > > > AVFilterLink *inlink, AVFrame *picr > > > > > > > return AVERROR(EAGAIN); > > > > > > > break; > > > > > > > } > > > > > > > + > > > > > > > +ret = av_frame_copy_side_data(out_frame->frame, in_frame- > > > > > > > > > > frame, > > > > > > 0); > > > > > > > +if (ret < 0) > > > > > > > +return ret; > > > > > > > + > > > > > > > out_frame->frame->pts = av_rescale_q(out_frame- > > > > > > > surface.Data.TimeStamp, > > > > > > > default_tb, outlink- > > > > > > > time_base); > > > > > > > > > > > > > > diff --git a/libavfilter/vf_overlay_qsv.c > > > > > > > > b/libavfilter/vf_overlay_qsv.c > > > > > > > index 7e76b39aa9..02518e020c 100644 > > > > > > > --- a/libavfilter/vf_overlay_qsv.c > > > > > > > +++ b/libavfilter/vf_overlay_qsv.c > > > > > > > @@ -231,13 +231,24 @@ static int process_frame(FFFrameSync *fs) > > > > > > > { > > > > > > > AVFilterContext *ctx = fs->parent; > > > > > > > QSVOverlayContext *s = fs->opaque; > > > > > > > +AVFrame *frame0 = NULL; > > > > > > > AVFrame*frame = NULL; > > > > > > > -int ret = 0, i; > > > > > > > +int ret = 0; > > > > > > > > > > > > > > -for (i = 0; i < ctx->nb_inputs; i++) { > > > > > > > +for (unsigned i = 0; i < ctx->nb_inputs; i++) { > > > > > > > ret = ff_framesync_get_frame(fs, i, &frame, 0); > > > > > > > -if (ret == 0) > > > > > > > -ret = ff_qsvvpp_filter_frame(s->qsv, ctx->inputs[i], > > > > > > > > frame); > > > > > > > + > > > > > > > +if (ret == 0) { > > > > > > > +AVFrame *temp; > > > > > > > + > > > > > > > +if (i == 0) > > > > > > > +frame0 = frame; > > > > > > > +else > > > > > > > +ret = av_frame_copy_side_data(frame, frame0, 0); > > > > > > > + > > > > > > > +ret = ret < 0 ? ret : ff_qsvvpp_filter_frame(s->qsv, > > > > ctx- > > > > > > > inputs[i], frame); > > > > > > > > > > > > I don't quite understand the ownership semantics here. This function > > > > > > does not free frame, so I assume ff_qsvvpp_filter_frame() takes > > > > > > ownership of it. That would mean you're not allowed to keep a > > > > > > pointer > > > > to > > > > > > it and access it later, because it might have already been freed. > > > > > > > > > > The filter is using framesync, which is taking care of the ownership. > > > > > ff_qsvvpp_filter_frame() clones or copies the frame, depending on > > > > > case. > > > > > Other than with the normal overlay filter, the frame from input0 is > > > > > not used for output. But the regular overlay filter has established > > > > > the > > > > > convention that side data from input0 is being kept at the output. > > > > > > > > Okay, if you're sure that framesync guarantees the frame remaining valid > > > > then I have no objections. > > > > > > > > But note that temp is unused and should be removed. > > > > > > OK, thanks. Let's see what Haihao says, he's closest to the subject at the > > > moment. > > > > Is it possible that the frame from input1 and the frame from input0 have the > > same type
Re: [FFmpeg-devel] [PATCH v9 1/2] avformat/imf: Demuxer
On Sun, Dec 12, 2021 at 7:58 PM Zane van Iperen wrote: > > > On 9/12/21 13:55, p...@sandflow.com wrote: > > > + > > +#define FF_UUID_FORMAT\ > > +"urn:uuid:%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-" \ > > +"%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" > > + > > +/** > > + * UUID as defined in IETF RFC 422 > > + */ > > +typedef uint8_t FFUUID[16]; > > + > > Perhaps change to FF_IMF_UUID_FORMAT and FFIMFUUID, unless you intend these > to be used for all of FFmpeg? Addressed by patchset v10. > > I also agree with Lynne that we shouldn't ad-hoc UUIDs. libuuid is nice > and wouldn't be too bad to add as a dependency. It'll also be handy if > some other part needs to handle UUIDs in the future. > > Even though it might not support "urn:uuid:", you can just offset the pointer > before giving it to uuid_parse (or uuid_parse_range). We would first need to make sure that the string is exactly 45 chars. On the output side, it looks like uuid_unparse() requires the caller to allocate a 36-char buffer. Wouldn't that complicate calls like the following: av_log(s, AV_LOG_DEBUG, "Found asset id: " FF_IMF_UUID_FORMAT "\n", UID_ARG(asset->uuid)); In fact, I wonder why libuuid [1] doesn't offer a simple printf format string, like FF_IMF_UUID_FORMAT? Maybe I missed it? [1] https://github.com/util-linux/util-linux/blob/master/libuuid/src/uuid.h > > Alternatively, if all you need to do is compare them, could you not > just compare the raw strings, skipping the parsing entirely? The sscanf() in ff_imf_xml_read_uuid() would be replaced by a strlen() followed by a memcpy(), and FFIMFUUID would be char[46] instead of uint8_t[16]. I am not convinced the code would be more maintainable/simpler. I am wondering if FFMPEG shouldn't ultimately define a thin wrapper over libuuid, like it does for memory and string functions? > > > +/** > > + * Parse an IMF CompositionPlaylist element into the FFIMFCPL data > > structure. > > + * @param[in] doc An XML document from which the CPL is read. > > + * @param[out] cpl Pointer to a memory area (allocated by the client), > > where the > > + * function writes a pointer to the newly constructed FFIMFCPL structure > > (or > > + * NULL if the CPL could not be parsed). The client is responsible for > > freeing > > + * the FFIMFCPL structure using ff_imf_cpl_free(). > > + * @return A non-zero value in case of an error. > > + */ > > +int ff_parse_imf_cpl_from_xml_dom(xmlDocPtr doc, FFIMFCPL **cpl); > > + > > ff_imf_parse_cpl_from_xml_dom(), ff_parse_* is taken. > Also for consistency with everything else. Addressed by patchset v10. > > > +/** > > + * Parse an IMF Composition Playlist document into the FFIMFCPL data > > structure. > > + * @param[in] in The context from which the CPL is read. > > + * @param[out] cpl Pointer to a memory area (allocated by the client), > > where the > > + * function writes a pointer to the newly constructed FFIMFCPL structure > > (or > > + * NULL if the CPL could not be parsed). The client is responsible for > > freeing > > + * the FFIMFCPL structure using ff_imf_cpl_free(). > > + * @return A non-zero value in case of an error. > > + */ > > +int ff_parse_imf_cpl(AVIOContext *in, FFIMFCPL **cpl); > > + > > Ditto. Addressed by patchset v10. > > > +/** > > + * Reads an unsigned 32-bit integer from an XML element > > + * @return 0 on success, < 0 AVERROR code on error. > > + */ > > +int ff_xml_read_uint32(xmlNodePtr element, uint32_t *number); > > + > > +/** > > + * Reads an AVRational from an XML element > > + * @return 0 on success, < 0 AVERROR code on error. > > + */ > > +int ff_xml_read_rational(xmlNodePtr element, AVRational *rational); > > + > > +/** > > + * Reads a UUID from an XML element > > + * @return 0 on success, < 0 AVERROR code on error. > > + */ > > +int ff_xml_read_uuid(xmlNodePtr element, uint8_t uuid[16]); > > + > > +/** > > + * Returns the first child element with the specified local name > > + * @return A pointer to the child element, or NULL if no such child > > element exists. > > + */ > > +xmlNodePtr ff_xml_get_child_element_by_name(xmlNodePtr parent, const char > > *name_utf8); > > + > > If these are only used for IMF, then ff_imf_xml_*(). Addressed by patchset v10. > Afaik FFmpeg doesn't have any centralised XML helpers (and perhaps it should, > there's a few > things that use libxml from a quick grep). Happy to look at refactoring the use of libxml after the IMF demuxer is merged -- just trying to keep the patch surface small. > > > + > > +const AVInputFormat ff_imf_demuxer = { > > +.name = "imf", > > +.long_name = NULL_IF_CONFIG_SMALL("IMF (Interoperable Master > > Format)"), > > +.flags_internal = FF_FMT_INIT_CLEANUP, > > +.priv_class = &imf_class, > > +.priv_data_size = sizeof(IMFContext), > > +.read_header= imf_read_header, > > +.read_packet= imf_read_packet, > > +.read_close = imf_close, >
[FFmpeg-devel] [PATCH] lavc/qsvenc: set base address for V plane
The SDK checks Data.V when using system memory for VP9 encoding. This fixed the error below: $ ffmpeg -qsv_device /dev/dri/renderD129 -f lavfi -i yuvtestsrc -c:v vp9_qsv -f null - [vp9_qsv @ 0x55b8387cbe90] Error during encoding: NULL pointer (-2) Video encoding failed --- libavcodec/qsvenc.c | 17 - 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 26a94cd419..7431ccfca5 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1389,8 +1389,23 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, qf->surface.Data.PitchLow = qf->frame->linesize[0]; qf->surface.Data.Y = qf->frame->data[0]; qf->surface.Data.UV= qf->frame->data[1]; -} +/* The SDK checks Data.V when using system memory for VP9 encoding */ +switch (frame->format) { +case AV_PIX_FMT_NV12: +qf->surface.Data.V = qf->surface.Data.UV + 1; +break; + +case AV_PIX_FMT_P010: +qf->surface.Data.V = qf->surface.Data.UV + 2; +break; + +default: +/* should not reach here */ +av_assert0(0); +break; +} +} qf->surface.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 9}); *new_frame = qf; -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 1/5] lavc/qsvenc: remove VC1 profiles
The SDK doesn't support VC1 encoding. In addition, both MFX_PROFILE_VC1_SIMPLE and MFX_PROFILE_HEVC_MAIN are 1 in the SDK, HEVC main profile is recognized as simple profile in the verbose output if don't remove VC1 profiles. $ ffmpeg -v verbose -qsv_device /dev/dri/renderD129 -f lavfi -i yuvtestsrc -c:v hevc_qsv -f null - [hevc_qsv @ 0x55bdf7eb4eb0] profile: simple; level: 21 --- libavcodec/qsvenc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 26a94cd419..dc0c45dc45 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -60,9 +60,6 @@ static const struct { { MFX_PROFILE_MPEG2_SIMPLE, "simple"}, { MFX_PROFILE_MPEG2_MAIN, "main" }, { MFX_PROFILE_MPEG2_HIGH, "high" }, -{ MFX_PROFILE_VC1_SIMPLE, "simple"}, -{ MFX_PROFILE_VC1_MAIN, "main" }, -{ MFX_PROFILE_VC1_ADVANCED, "advanced" }, #if QSV_VERSION_ATLEAST(1, 8) { MFX_PROFILE_HEVC_MAIN,"main" }, { MFX_PROFILE_HEVC_MAIN10, "main10"}, -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 2/5] lavc/qsvenc: define profile array per codec
The SDK defines HEVC, VP9 and AV1 profiles in the same values e.g. MFX_PROFILE_HEVC_MAIN =1, MFX_PROFILE_VP9_0 =1, MFX_PROFILE_AV1_MAIN =1, To avoid potential errors when adding VP9, AV1 profiles later, this patch defines profile array per codec. --- libavcodec/qsvenc.c | 47 + 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index dc0c45dc45..7dab8bab0f 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -41,10 +41,12 @@ #include "qsv_internal.h" #include "qsvenc.h" -static const struct { +struct profile_names { mfxU16 profile; const char *name; -} profile_names[] = { +}; + +static const struct profile_names avc_profiles[] = { { MFX_PROFILE_AVC_BASELINE, "baseline" }, { MFX_PROFILE_AVC_MAIN, "main" }, { MFX_PROFILE_AVC_EXTENDED, "extended" }, @@ -57,9 +59,15 @@ static const struct { { MFX_PROFILE_AVC_CONSTRAINED_HIGH, "constrained high" }, { MFX_PROFILE_AVC_PROGRESSIVE_HIGH, "progressive high" }, #endif +}; + +static const struct profile_names mpeg2_profiles[] = { { MFX_PROFILE_MPEG2_SIMPLE, "simple"}, { MFX_PROFILE_MPEG2_MAIN, "main" }, { MFX_PROFILE_MPEG2_HIGH, "high" }, +}; + +static const struct profile_names hevc_profiles[] = { #if QSV_VERSION_ATLEAST(1, 8) { MFX_PROFILE_HEVC_MAIN,"main" }, { MFX_PROFILE_HEVC_MAIN10, "main10"}, @@ -68,12 +76,35 @@ static const struct { #endif }; -static const char *print_profile(mfxU16 profile) +static const char *print_profile(enum AVCodecID codec_id, mfxU16 profile) { -int i; -for (i = 0; i < FF_ARRAY_ELEMS(profile_names); i++) -if (profile == profile_names[i].profile) -return profile_names[i].name; +const struct profile_names *profiles; +int i, num_profiles; + +switch (codec_id) { +case AV_CODEC_ID_H264: +profiles = avc_profiles; +num_profiles = FF_ARRAY_ELEMS(avc_profiles); +break; + +case AV_CODEC_ID_MPEG2VIDEO: +profiles = mpeg2_profiles; +num_profiles = FF_ARRAY_ELEMS(mpeg2_profiles); +break; + +case AV_CODEC_ID_HEVC: +profiles = hevc_profiles; +num_profiles = FF_ARRAY_ELEMS(hevc_profiles); +break; + +default: +return "unknown"; +} + +for (i = 0; i < num_profiles; i++) +if (profile == profiles[i].profile) +return profiles[i].name; + return "unknown"; } @@ -143,7 +174,7 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, #endif av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n", - print_profile(info->CodecProfile), info->CodecLevel); + print_profile(avctx->codec_id, info->CodecProfile), info->CodecLevel); av_log(avctx, AV_LOG_VERBOSE, "GopPicSize: %"PRIu16"; GopRefDist: %"PRIu16"; GopOptFlag: ", info->GopPicSize, info->GopRefDist); -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 3/5] lavc/qsvenc: add VP9 profiles
--- libavcodec/qsvenc.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 7dab8bab0f..a2a8a79189 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -76,6 +76,15 @@ static const struct profile_names hevc_profiles[] = { #endif }; +static const struct profile_names vp9_profiles[] = { +#if QSV_VERSION_ATLEAST(1, 19) +{ MFX_PROFILE_VP9_0,"0" }, +{ MFX_PROFILE_VP9_1,"1" }, +{ MFX_PROFILE_VP9_2,"2" }, +{ MFX_PROFILE_VP9_3,"3" }, +#endif +}; + static const char *print_profile(enum AVCodecID codec_id, mfxU16 profile) { const struct profile_names *profiles; @@ -97,6 +106,11 @@ static const char *print_profile(enum AVCodecID codec_id, mfxU16 profile) num_profiles = FF_ARRAY_ELEMS(hevc_profiles); break; +case AV_CODEC_ID_VP9: +profiles = vp9_profiles; +num_profiles = FF_ARRAY_ELEMS(vp9_profiles); +break; + default: return "unknown"; } -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 4/5] lavc/qsvenc: dump parameters for VP9 encoding in verbose mode
--- libavcodec/qsvenc.c | 80 + 1 file changed, 80 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index a2a8a79189..106438f227 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -343,6 +343,84 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, } +static void dump_video_vp9_param(AVCodecContext *avctx, QSVEncContext *q, + mfxExtBuffer **coding_opts) +{ +mfxInfoMFX *info = &q->param.mfx; +#if QSV_HAVE_EXT_VP9_PARAM +mfxExtVP9Param *vp9_param = (mfxExtVP9Param *)coding_opts[0]; +#endif +#if QSV_HAVE_CO2 +mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[1]; +#endif + +av_log(avctx, AV_LOG_VERBOSE, "profile: %s \n", + print_profile(avctx->codec_id, info->CodecProfile)); + +av_log(avctx, AV_LOG_VERBOSE, "GopPicSize: %"PRIu16"; GopRefDist: %"PRIu16"; GopOptFlag: ", + info->GopPicSize, info->GopRefDist); +if (info->GopOptFlag & MFX_GOP_CLOSED) +av_log(avctx, AV_LOG_VERBOSE, "closed "); +if (info->GopOptFlag & MFX_GOP_STRICT) +av_log(avctx, AV_LOG_VERBOSE, "strict "); +av_log(avctx, AV_LOG_VERBOSE, "; IdrInterval: %"PRIu16"\n", info->IdrInterval); + +av_log(avctx, AV_LOG_VERBOSE, "TargetUsage: %"PRIu16"; RateControlMethod: %s\n", + info->TargetUsage, print_ratecontrol(info->RateControlMethod)); + +if (info->RateControlMethod == MFX_RATECONTROL_CBR || +info->RateControlMethod == MFX_RATECONTROL_VBR) { +av_log(avctx, AV_LOG_VERBOSE, + "BufferSizeInKB: %"PRIu16"; InitialDelayInKB: %"PRIu16"; TargetKbps: %"PRIu16"; MaxKbps: %"PRIu16"; BRCParamMultiplier: %"PRIu16"\n", + info->BufferSizeInKB, info->InitialDelayInKB, info->TargetKbps, info->MaxKbps, info->BRCParamMultiplier); +} else if (info->RateControlMethod == MFX_RATECONTROL_CQP) { +av_log(avctx, AV_LOG_VERBOSE, "QPI: %"PRIu16"; QPP: %"PRIu16"; QPB: %"PRIu16"\n", + info->QPI, info->QPP, info->QPB); +} +#if QSV_HAVE_ICQ +else if (info->RateControlMethod == MFX_RATECONTROL_ICQ) { +av_log(avctx, AV_LOG_VERBOSE, "ICQQuality: %"PRIu16"\n", info->ICQQuality); +} +#endif +else { +av_log(avctx, AV_LOG_VERBOSE, "Unsupported ratecontrol method: %d \n", info->RateControlMethod); +} + +av_log(avctx, AV_LOG_VERBOSE, "NumRefFrame: %"PRIu16"\n", info->NumRefFrame); + +#if QSV_HAVE_CO2 +av_log(avctx, AV_LOG_VERBOSE, + "IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n", + co2->IntRefType, co2->IntRefCycleSize, co2->IntRefQPDelta); + +av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSize: %d; ", co2->MaxFrameSize); +av_log(avctx, AV_LOG_VERBOSE, "\n"); + +av_log(avctx, AV_LOG_VERBOSE, + "BitrateLimit: %s; MBBRC: %s; ExtBRC: %s\n", + print_threestate(co2->BitrateLimit), print_threestate(co2->MBBRC), + print_threestate(co2->ExtBRC)); + +#if QSV_HAVE_VDENC +av_log(avctx, AV_LOG_VERBOSE, "VDENC: %s\n", print_threestate(info->LowPower)); +#endif + +#if QSV_VERSION_ATLEAST(1, 9) +av_log(avctx, AV_LOG_VERBOSE, + "MinQPI: %"PRIu8"; MaxQPI: %"PRIu8"; MinQPP: %"PRIu8"; MaxQPP: %"PRIu8"; MinQPB: %"PRIu8"; MaxQPB: %"PRIu8"\n", + co2->MinQPI, co2->MaxQPI, co2->MinQPP, co2->MaxQPP, co2->MinQPB, co2->MaxQPB); +#endif +#endif + +av_log(avctx, AV_LOG_VERBOSE, "FrameRateExtD: %"PRIu32"; FrameRateExtN: %"PRIu32" \n", + info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN); + +#if QSV_HAVE_EXT_VP9_PARAM +av_log(avctx, AV_LOG_VERBOSE, "WriteIVFHeaders: %s \n", + print_threestate(vp9_param->WriteIVFHeaders)); +#endif +} + static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) { const char *rc_desc; @@ -941,6 +1019,8 @@ static int qsv_retrieve_enc_vp9_params(AVCodecContext *avctx, QSVEncContext *q) q->packet_size = q->param.mfx.BufferSizeInKB * q->param.mfx.BRCParamMultiplier * 1000; +dump_video_vp9_param(avctx, q, ext_buffers); + return 0; } -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 5/5] lavc/qsvenc: dump parameters for mjpeg encoding in verbose mode
--- libavcodec/qsvenc.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 106438f227..92a8b49fe3 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -421,6 +421,18 @@ static void dump_video_vp9_param(AVCodecContext *avctx, QSVEncContext *q, #endif } +static void dump_video_mjpeg_param(AVCodecContext *avctx, QSVEncContext *q) +{ +mfxInfoMFX *info = &q->param.mfx; + +av_log(avctx, AV_LOG_VERBOSE, "Interleaved: %"PRIu16" \n", info->Interleaved); +av_log(avctx, AV_LOG_VERBOSE, "Quality: %"PRIu16" \n", info->Quality); +av_log(avctx, AV_LOG_VERBOSE, "RestartInterval: %"PRIu16" \n", info->RestartInterval); + +av_log(avctx, AV_LOG_VERBOSE, "FrameRateExtD: %"PRIu32"; FrameRateExtN: %"PRIu32" \n", + info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN); +} + static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) { const char *rc_desc; @@ -970,6 +982,8 @@ static int qsv_retrieve_enc_jpeg_params(AVCodecContext *avctx, QSVEncContext *q) if (q->packet_size == 0) q->packet_size = q->param.mfx.FrameInfo.Height * q->param.mfx.FrameInfo.Width * 4; +dump_video_mjpeg_param(avctx, q); + return 0; } -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v3 2/2] avcodec/vpp_qsv: Copy side data from input to output frame
> -Original Message- > From: ffmpeg-devel On Behalf Of Xiang, > Haihao > Sent: Monday, December 13, 2021 6:55 AM > To: ffmpeg-devel@ffmpeg.org > Subject: Re: [FFmpeg-devel] [PATCH v3 2/2] avcodec/vpp_qsv: Copy side data > from input to output frame > > > > > -Original Message- > > > From: ffmpeg-devel On Behalf Of Xiang, > > > Haihao > > > Sent: Thursday, December 9, 2021 9:35 AM > > > To: ffmpeg-devel@ffmpeg.org > > > Subject: Re: [FFmpeg-devel] [PATCH v3 2/2] avcodec/vpp_qsv: Copy side > data > > > from input to output frame > > > > > > On Tue, 2021-12-07 at 12:39 +, Soft Works wrote: > > > > > -Original Message- > > > > > From: ffmpeg-devel On Behalf Of > Anton > > > > > Khirnov > > > > > Sent: Tuesday, December 7, 2021 12:51 PM > > > > > To: FFmpeg development discussions and patches de...@ffmpeg.org> > > > > > Subject: Re: [FFmpeg-devel] [PATCH v3 2/2] avcodec/vpp_qsv: Copy side > > > > > > data > > > > > from input to output frame > > > > > > > > > > Quoting Soft Works (2021-12-07 09:55:37) > > > > > > > > > > > > > > > > > > > -Original Message- > > > > > > > From: ffmpeg-devel On Behalf Of > > > > > > Anton > > > > > > > Khirnov > > > > > > > Sent: Tuesday, December 7, 2021 9:04 AM > > > > > > > To: ffmpeg-devel@ffmpeg.org > > > > > > > Subject: Re: [FFmpeg-devel] [PATCH v3 2/2] avcodec/vpp_qsv: Copy > > > > > > > side > > > > > > > > > > data > > > > > > > from input to output frame > > > > > > > > > > > > > > Quoting Soft Works (2021-12-03 08:58:31) > > > > > > > > Signed-off-by: softworkz > > > > > > > > --- > > > > > > > > libavfilter/qsvvpp.c | 5 + > > > > > > > > libavfilter/vf_overlay_qsv.c | 19 +++ > > > > > > > > 2 files changed, 20 insertions(+), 4 deletions(-) > > > > > > > > > > > > > > > > diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c > > > > > > > > index d1218355c7..b291216292 100644 > > > > > > > > --- a/libavfilter/qsvvpp.c > > > > > > > > +++ b/libavfilter/qsvvpp.c > > > > > > > > @@ -849,6 +849,11 @@ int ff_qsvvpp_filter_frame(QSVVPPContext > *s, > > > > > > > > > > > > > > AVFilterLink *inlink, AVFrame *picr > > > > > > > > return AVERROR(EAGAIN); > > > > > > > > break; > > > > > > > > } > > > > > > > > + > > > > > > > > +ret = av_frame_copy_side_data(out_frame->frame, > in_frame- > > > > > > > > > > > > frame, > > > > > > > 0); > > > > > > > > +if (ret < 0) > > > > > > > > +return ret; > > > > > > > > + > > > > > > > > out_frame->frame->pts = av_rescale_q(out_frame- > > > > > > > > surface.Data.TimeStamp, > > > > > > > > default_tb, > outlink- > > > > > > > > time_base); > > > > > > > > > > > > > > > > diff --git a/libavfilter/vf_overlay_qsv.c > > > > > > > > > > b/libavfilter/vf_overlay_qsv.c > > > > > > > > index 7e76b39aa9..02518e020c 100644 > > > > > > > > --- a/libavfilter/vf_overlay_qsv.c > > > > > > > > +++ b/libavfilter/vf_overlay_qsv.c > > > > > > > > @@ -231,13 +231,24 @@ static int process_frame(FFFrameSync *fs) > > > > > > > > { > > > > > > > > AVFilterContext *ctx = fs->parent; > > > > > > > > QSVOverlayContext *s = fs->opaque; > > > > > > > > +AVFrame *frame0 = NULL; > > > > > > > > AVFrame*frame = NULL; > > > > > > > > -int ret = 0, i; > > > > > > > > +int ret = 0; > > > > > > > > > > > > > > > > -for (i = 0; i < ctx->nb_inputs; i++) { > > > > > > > > +for (unsigned i = 0; i < ctx->nb_inputs; i++) { > > > > > > > > ret = ff_framesync_get_frame(fs, i, &frame, 0); > > > > > > > > -if (ret == 0) > > > > > > > > -ret = ff_qsvvpp_filter_frame(s->qsv, ctx- > >inputs[i], > > > > > > > > > > frame); > > > > > > > > + > > > > > > > > +if (ret == 0) { > > > > > > > > +AVFrame *temp; > > > > > > > > + > > > > > > > > +if (i == 0) > > > > > > > > +frame0 = frame; > > > > > > > > +else > > > > > > > > +ret = av_frame_copy_side_data(frame, frame0, > 0); > > > > > > > > + > > > > > > > > +ret = ret < 0 ? ret : ff_qsvvpp_filter_frame(s- > >qsv, > > > > > > ctx- > > > > > > > > inputs[i], frame); > > > > > > > > > > > > > > I don't quite understand the ownership semantics here. This > function > > > > > > > does not free frame, so I assume ff_qsvvpp_filter_frame() takes > > > > > > > ownership of it. That would mean you're not allowed to keep a > > > > > > > pointer > > > > > > to > > > > > > > it and access it later, because it might have already been freed. > > > > > > > > > > > > The filter is using framesync, which is taking care of the > ownership. > > > > > > ff_qsvvpp_filter_frame() clones or copies the frame, depending on > > > > > > case. > > > > > > Other than with the normal overlay filter, the frame from input0 is > > > > > > not used for output. But the regular over
[FFmpeg-devel] [PATCH v4 00/13] dshow enhancements
This series solves some outstanding bugs in the dshow device, implements get_device_list so that `ffmpeg -sources dshow` works and adds logic to select a video format with extended color information (color range, space, etc) if exposed by the device. This is a new version of part of the patch series in https://ffmpeg.org/pipermail/ffmpeg-devel/2021-July/282073.html, addressing review comments i got there. They have been previously OK'ed offlist by the dshow maintainer Roger Pack. Specifically, these patches are the enhancements that should be uncontroversial as they do not touch the avformat API. I hope they can be swiftly pushed by someone, then i'll re-send the other more controversial patches on top of these. Diederick Niehorster (13): avdevice/dshow: prevent NULL access avdevice/dshow: implement option to use device video timestamps avdevice/dshow: add use_video_device_timestamps to docs avdevice/dshow: query graph and sample time only once avdevice/dshow: handle unknown sample time avdevice/dshow: set no-seek flags avdevice/dshow: implement get_device_list avdevice/dshow: list_devices: show media type(s) per device avdevice: add info about media types(s) to AVDeviceInfo avdevice/dshow: add media type info to get_device_list fftools: provide media type info for devices avdevice/dshow: discover source color range/space/etc avdevice/dshow: select format with extended color info doc/indevs.texi | 6 + fftools/cmdutils.c | 34 +- libavdevice/avdevice.c | 2 + libavdevice/avdevice.h | 2 + libavdevice/dshow.c | 838 +++- libavdevice/dshow_capture.h | 1 + libavdevice/dshow_pin.c | 46 +- libavdevice/version.h | 2 +- 8 files changed, 797 insertions(+), 134 deletions(-) -- 2.28.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v4 01/13] avdevice/dshow: prevent NULL access
list_options true would crash when both a video and an audio device were specified as input. Crash would occur on line 784 because ctx->device_unique_name[otherDevType] would be NULL Signed-off-by: Diederick Niehorster --- libavdevice/dshow.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index ef78781865..cc0bef0474 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -708,9 +708,9 @@ dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum, if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_unique_name)) < 0) return r; ctx->device_filter[devtype] = device_filter; +ctx->device_unique_name[devtype] = device_unique_name; if ((r = dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, NULL)) < 0) return r; -av_freep(&device_unique_name); return 0; } @@ -1143,6 +1143,7 @@ static int dshow_read_header(AVFormatContext *avctx) } } } +// don't exit yet, allow it to list crossbar options in dshow_open_device } if (ctx->device_name[VideoDevice]) { if ((r = dshow_open_device(avctx, devenum, VideoDevice, VideoSourceDevice)) < 0 || -- 2.28.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v4 02/13] avdevice/dshow: implement option to use device video timestamps
The dshow avdevice ignores timestamps for video frames provided by the DirectShow device, instead using wallclock time, apparently because the implementer of this code had a device that provided unreliable timestamps. Me (and others) would like to use the device's timestamps. The new use_video_device_timestamps option for dshow device enables them to do so. Since the majority of video devices out there probably provide fine timestamps, this patch sets the default to using the device timestamps, which means best fidelity timestamps are used by default. Using the new option, the user can switch this off and revert to the old behavior, so a fall back remains available in case the device provides broken timestamps. Closes: #8620 Signed-off-by: Diederick Niehorster --- libavdevice/dshow.c | 1 + libavdevice/dshow_capture.h | 1 + libavdevice/dshow_pin.c | 11 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index cc0bef0474..5e6eb9c85d 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -1310,6 +1310,7 @@ static const AVOption options[] = { { "audio_device_save", "save audio capture filter device (and properties) to file", OFFSET(audio_filter_save_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { "video_device_load", "load video capture filter device (and properties) from file", OFFSET(video_filter_load_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { "video_device_save", "save video capture filter device (and properties) to file", OFFSET(video_filter_save_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, +{ "use_video_device_timestamps", "use device instead of wallclock timestamps for video frames", OFFSET(use_video_device_timestamps), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DEC }, { NULL }, }; diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index 06ded2ba96..5a2691518c 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -312,6 +312,7 @@ struct dshow_ctx { char *audio_filter_save_file; char *video_filter_load_file; char *video_filter_save_file; +int use_video_device_timestamps; IBaseFilter *device_filter[2]; IPin*device_pin[2]; diff --git a/libavdevice/dshow_pin.c b/libavdevice/dshow_pin.c index 3dae405e65..8e56dccbfe 100644 --- a/libavdevice/dshow_pin.c +++ b/libavdevice/dshow_pin.c @@ -309,10 +309,14 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) if (!sample) return E_POINTER; +priv_data = pin->filter->priv_data; +s = priv_data; +ctx = s->priv_data; + IMediaSample_GetTime(sample, &orig_curtime, &dummy); orig_curtime += pin->filter->start_time; IReferenceClock_GetTime(clock, &graphtime); -if (devtype == VideoDevice) { +if (devtype == VideoDevice && !ctx->use_video_device_timestamps) { /* PTS from video devices is unreliable. */ IReferenceClock_GetTime(clock, &curtime); } else { @@ -322,7 +326,7 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) like 437650244077016960 which FFmpeg doesn't like. TODO figure out math. For now just drop them. */ av_log(NULL, AV_LOG_DEBUG, -"dshow dropping initial (or ending) audio frame with odd PTS too high %"PRId64"\n", curtime); +"dshow dropping initial (or ending) frame with odd PTS too high %"PRId64"\n", curtime); return S_OK; } curtime += pin->filter->start_time; @@ -330,9 +334,6 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) buf_size = IMediaSample_GetActualDataLength(sample); IMediaSample_GetPointer(sample, &buf); -priv_data = pin->filter->priv_data; -s = priv_data; -ctx = s->priv_data; index = pin->filter->stream_index; av_log(NULL, AV_LOG_VERBOSE, "dshow passing through packet of type %s size %8d " -- 2.28.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v4 03/13] avdevice/dshow: add use_video_device_timestamps to docs
Signed-off-by: Diederick Niehorster --- doc/indevs.texi | 6 ++ 1 file changed, 6 insertions(+) diff --git a/doc/indevs.texi b/doc/indevs.texi index 5be647f70a..9d8020311a 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -625,6 +625,12 @@ Save the currently used video capture filter device and its parameters (if the filter supports it) to a file. If a file with the same name exists it will be overwritten. +@item use_video_device_timestamps +If set to @option{false}, the timestamp for video frames will be +derived from the wallclock instead of the timestamp provided by +the capture device. This allows working around devices that +provide unreliable timestamps. + @end table @subsection Examples -- 2.28.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v4 04/13] avdevice/dshow: query graph and sample time only once
No need to query twice, use value we've already unconditionally got. Improve variable names Signed-off-by: Diederick Niehorster --- libavdevice/dshow_pin.c | 28 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/libavdevice/dshow_pin.c b/libavdevice/dshow_pin.c index 8e56dccbfe..1d0e880480 100644 --- a/libavdevice/dshow_pin.c +++ b/libavdevice/dshow_pin.c @@ -295,9 +295,10 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) uint8_t *buf; int buf_size; /* todo should be a long? */ int index; -int64_t curtime; -int64_t orig_curtime; +int64_t chosentime; +int64_t sampletime; int64_t graphtime; +int use_sample_time = 1; const char *devtypename = (devtype == VideoDevice) ? "video" : "audio"; IReferenceClock *clock = pin->filter->clock; int64_t dummy; @@ -313,24 +314,27 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) s = priv_data; ctx = s->priv_data; -IMediaSample_GetTime(sample, &orig_curtime, &dummy); -orig_curtime += pin->filter->start_time; +IMediaSample_GetTime(sample, &sampletime, &dummy); IReferenceClock_GetTime(clock, &graphtime); if (devtype == VideoDevice && !ctx->use_video_device_timestamps) { /* PTS from video devices is unreliable. */ -IReferenceClock_GetTime(clock, &curtime); +chosentime = graphtime; +use_sample_time = 0; } else { -IMediaSample_GetTime(sample, &curtime, &dummy); -if(curtime > 40LL) { +if (sampletime > 40LL) { /* initial frames sometimes start < 0 (shown as a very large number here, - like 437650244077016960 which FFmpeg doesn't like. + like 437650244077016960 which FFmpeg doesn't like). TODO figure out math. For now just drop them. */ av_log(NULL, AV_LOG_DEBUG, -"dshow dropping initial (or ending) frame with odd PTS too high %"PRId64"\n", curtime); +"dshow dropping initial (or ending) frame with odd PTS too high %"PRId64"\n", sampletime); return S_OK; } -curtime += pin->filter->start_time; +chosentime = sampletime; } +// media sample time is relative to graph start time +sampletime += pin->filter->start_time; +if (use_sample_time) +chosentime += pin->filter->start_time; buf_size = IMediaSample_GetActualDataLength(sample); IMediaSample_GetPointer(sample, &buf); @@ -338,8 +342,8 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) av_log(NULL, AV_LOG_VERBOSE, "dshow passing through packet of type %s size %8d " "timestamp %"PRId64" orig timestamp %"PRId64" graph timestamp %"PRId64" diff %"PRId64" %s\n", -devtypename, buf_size, curtime, orig_curtime, graphtime, graphtime - orig_curtime, ctx->device_name[devtype]); -pin->filter->callback(priv_data, index, buf, buf_size, curtime, devtype); +devtypename, buf_size, chosentime, sampletime, graphtime, graphtime - sampletime, ctx->device_name[devtype]); +pin->filter->callback(priv_data, index, buf, buf_size, chosentime, devtype); return S_OK; } -- 2.28.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v4 05/13] avdevice/dshow: handle unknown sample time
GetTime may return an error indication that the sample has not timestamps, or may return a NULL start time. In those cases, fall back to graph time. Better debug message in case sample dropped: could now be audio or video frame Signed-off-by: Diederick Niehorster --- libavdevice/dshow_pin.c | 19 --- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/libavdevice/dshow_pin.c b/libavdevice/dshow_pin.c index 1d0e880480..310f48c85e 100644 --- a/libavdevice/dshow_pin.c +++ b/libavdevice/dshow_pin.c @@ -295,14 +295,15 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) uint8_t *buf; int buf_size; /* todo should be a long? */ int index; -int64_t chosentime; -int64_t sampletime; -int64_t graphtime; +int64_t chosentime = 0; +int64_t sampletime = 0; +int64_t graphtime = 0; int use_sample_time = 1; const char *devtypename = (devtype == VideoDevice) ? "video" : "audio"; IReferenceClock *clock = pin->filter->clock; int64_t dummy; struct dshow_ctx *ctx; +HRESULT hr; dshowdebug("ff_dshow_meminputpin_Receive(%p)\n", this); @@ -314,22 +315,26 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) s = priv_data; ctx = s->priv_data; -IMediaSample_GetTime(sample, &sampletime, &dummy); +hr = IMediaSample_GetTime(sample, &sampletime, &dummy); IReferenceClock_GetTime(clock, &graphtime); if (devtype == VideoDevice && !ctx->use_video_device_timestamps) { /* PTS from video devices is unreliable. */ chosentime = graphtime; use_sample_time = 0; } else { -if (sampletime > 40LL) { +if (hr == VFW_E_SAMPLE_TIME_NOT_SET || sampletime == 0) { +chosentime = graphtime; +use_sample_time = 0; +} +else if (sampletime > 40LL) { /* initial frames sometimes start < 0 (shown as a very large number here, like 437650244077016960 which FFmpeg doesn't like). TODO figure out math. For now just drop them. */ av_log(NULL, AV_LOG_DEBUG, "dshow dropping initial (or ending) frame with odd PTS too high %"PRId64"\n", sampletime); return S_OK; -} -chosentime = sampletime; +} else +chosentime = sampletime; } // media sample time is relative to graph start time sampletime += pin->filter->start_time; -- 2.28.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v4 06/13] avdevice/dshow: set no-seek flags
avdevice/dshow is a realtime device and as such does not support seeking. Therefore, its demuxer format should define the AVFMT_NOBINSEARCH, AVFMT_NOGENSEARCH and AVFMT_NO_BYTE_SEEK flags. With these flags set, attempting to seek (with, e.g., avformat_seek_file()) correctly yields -1 (operation not permitted) instead of -22 (invalid argument). This actually seems to apply to many other devices, at least the gdigrab, v4l2, vfwcap, x11grab, fbdev, kmsgrab and android_camera devices, from reading the source. Signed-off-by: Diederick Niehorster --- libavdevice/dshow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 5e6eb9c85d..0ef3b3d13e 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -1329,6 +1329,6 @@ const AVInputFormat ff_dshow_demuxer = { .read_header= dshow_read_header, .read_packet= dshow_read_packet, .read_close = dshow_read_close, -.flags = AVFMT_NOFILE, +.flags = AVFMT_NOFILE | AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK, .priv_class = &dshow_class, }; -- 2.28.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v4 07/13] avdevice/dshow: implement get_device_list
Needed to enable programmatic discovery of DirectShow devices Signed-off-by: Diederick Niehorster --- libavdevice/dshow.c | 80 + 1 file changed, 73 insertions(+), 7 deletions(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 0ef3b3d13e..8c257ca8e7 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -202,11 +202,14 @@ fail: * retrieve the device with type specified by devtype and return the * pointer to the object found in *pfilter. * If pfilter is NULL, list all device names. + * If device_list is not NULL, populate it with found devices instead of + * outputting device names to log */ static int dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype, -IBaseFilter **pfilter, char **device_unique_name) +IBaseFilter **pfilter, char **device_unique_name, +AVDeviceInfoList **device_list) { struct dshow_ctx *ctx = avctx->priv_data; IBaseFilter *device_filter = NULL; @@ -238,6 +241,7 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, IBindCtx *bind_ctx = NULL; LPOLESTR olestr = NULL; LPMALLOC co_malloc = NULL; +AVDeviceInfo *device = NULL; int i; r = CoGetMalloc(1, &co_malloc); @@ -282,11 +286,39 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, // success, loop will end now } } else { -av_log(avctx, AV_LOG_INFO, " \"%s\"\n", friendly_name); -av_log(avctx, AV_LOG_INFO, "Alternative name \"%s\"\n", unique_name); +if (device_list) { +device = av_mallocz(sizeof(AVDeviceInfo)); +if (!device) +goto fail1; + +device->device_name = av_strdup(friendly_name); +device->device_description = av_strdup(unique_name); +if (!device->device_name || !device->device_description) +goto fail1; + +// store to device_list output +if (av_reallocp_array(&(*device_list)->devices, + (*device_list)->nb_devices + 1, + sizeof(*(*device_list)->devices)) < 0) +goto fail1; +(*device_list)->devices[(*device_list)->nb_devices] = device; +(*device_list)->nb_devices++; +device = NULL; // copied into array, make sure not freed below +} +else { +av_log(avctx, AV_LOG_INFO, " \"%s\"\n", friendly_name); +av_log(avctx, AV_LOG_INFO, "Alternative name \"%s\"\n", unique_name); +} } fail1: +if (device) { +if (device->device_name) +av_freep(&device->device_name); +if (device->device_name) +av_freep(&device->device_description); +av_free(device); +} if (olestr && co_malloc) IMalloc_Free(co_malloc, olestr); if (bind_ctx) @@ -312,6 +344,39 @@ fail1: return 0; } +static int dshow_get_device_list(AVFormatContext *avctx, AVDeviceInfoList *device_list) +{ +struct dshow_ctx *ctx = avctx->priv_data; +ICreateDevEnum *devenum = NULL; +int r; +int ret = AVERROR(EIO); + +if (!device_list) +return AVERROR(EINVAL); + +CoInitialize(0); + +r = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, +&IID_ICreateDevEnum, (void**)&devenum); +if (r != S_OK) { +av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n"); +goto error; +} + +ret = dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, NULL, NULL, &device_list); +if (ret < S_OK) +goto error; +ret = dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, NULL, NULL, &device_list); + +error: +if (devenum) +ICreateDevEnum_Release(devenum); + +CoUninitialize(); + +return ret; +} + /** * Cycle through available formats using the specified pin, * try to set parameters specified through AVOptions and if successful @@ -705,7 +770,7 @@ dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum, char *device_unique_name = NULL; int r; -if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_unique_name)) < 0) +if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_unique_name, NULL)) < 0) return r; ctx->device_filter[devtype] = device_filter; ctx->device_unique_name[devtype] = device_unique_name; @@ -765,7 +830,7 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum, av_log(avctx, AV_LOG_INFO, "C
[FFmpeg-devel] [PATCH v4 08/13] avdevice/dshow: list_devices: show media type(s) per device
the list_devices option of dshow didn't indicate whether a specific device provides audio or video output. This patch iterates through all media formats of all pins exposed by the device to see what types it provides for capture, and prints this to the console for each device. Importantly, this now allows to find devices that provide both audio and video, and devices that provide neither. Signed-off-by: Diederick Niehorster --- libavdevice/dshow.c | 103 +--- 1 file changed, 98 insertions(+), 5 deletions(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 8c257ca8e7..f25537db5c 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -197,6 +197,79 @@ fail: return; } +static void dshow_get_device_media_types(AVFormatContext *avctx, enum dshowDeviceType devtype, + enum dshowSourceFilterType sourcetype, IBaseFilter *device_filter, + enum AVMediaType **media_types, int *nb_media_types) +{ +struct dshow_ctx *ctx = avctx->priv_data; +IEnumPins *pins = 0; +IPin *pin; +int has_audio = 0, has_video = 0; + +if (IBaseFilter_EnumPins(device_filter, &pins) != S_OK) +return; + +while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) { +IKsPropertySet *p = NULL; +PIN_INFO info = { 0 }; +GUID category; +DWORD r2; +IEnumMediaTypes *types = NULL; +AM_MEDIA_TYPE *type; + +if (IPin_QueryPinInfo(pin, &info) != S_OK) +goto next; +IBaseFilter_Release(info.pFilter); + +if (info.dir != PINDIR_OUTPUT) +goto next; +if (IPin_QueryInterface(pin, &IID_IKsPropertySet, (void **) &p) != S_OK) +goto next; +if (IKsPropertySet_Get(p, &ROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, + NULL, 0, &category, sizeof(GUID), &r2) != S_OK) +goto next; +if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE)) +goto next; + +if (IPin_EnumMediaTypes(pin, &types) != S_OK) +goto next; + +// enumerate media types exposed by pin +// NB: don't know if a pin can expose both audio and video, check 'm all to be safe +IEnumMediaTypes_Reset(types); +while (IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) { +if (IsEqualGUID(&type->majortype, &MEDIATYPE_Video)) { +has_video = 1; +} else if (IsEqualGUID(&type->majortype, &MEDIATYPE_Audio)) { +has_audio = 1; +} +CoTaskMemFree(type); +} + +next: +if (types) +IEnumMediaTypes_Release(types); +if (p) +IKsPropertySet_Release(p); +if (pin) +IPin_Release(pin); +} + +IEnumPins_Release(pins); + +if (has_audio || has_video) { +int nb_types = has_audio + has_video; +*media_types = av_malloc_array(nb_types, sizeof(enum AVMediaType)); +if (*media_types) { +if (has_audio) +(*media_types)[0] = AVMEDIA_TYPE_AUDIO; +if (has_video) +(*media_types)[0 + has_audio] = AVMEDIA_TYPE_VIDEO; +*nb_media_types = nb_types; +} +} +} + /** * Cycle through available devices using the device enumerator devenum, * retrieve the device with type specified by devtype and return the @@ -242,6 +315,8 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, LPOLESTR olestr = NULL; LPMALLOC co_malloc = NULL; AVDeviceInfo *device = NULL; +enum AVMediaType *media_types = NULL; +int nb_media_types = 0; int i; r = CoGetMalloc(1, &co_malloc); @@ -286,6 +361,12 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, // success, loop will end now } } else { +// get media types exposed by pins of device +if (IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void* ) &device_filter) == S_OK) { +dshow_get_device_media_types(avctx, devtype, sourcetype, device_filter, &media_types, &nb_media_types); +IBaseFilter_Release(device_filter); +device_filter = NULL; +} if (device_list) { device = av_mallocz(sizeof(AVDeviceInfo)); if (!device) @@ -306,12 +387,26 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, device = NULL; // copied into array, make sure not freed below } else { -av_log(avctx, AV_LOG_INFO, " \"%s\"\n", friendly_name); -av_log(avctx, AV_LOG_INFO, "Alternative name \"%s\"\n", unique_name); +av_log(avctx, AV_LOG_INFO, "\"%s\"", friendly_name); +if (nb_media_types > 0 && media_types) { +
[FFmpeg-devel] [PATCH v4 09/13] avdevice: add info about media types(s) to AVDeviceInfo
An avdevice, regardless of whether its category says its an audio or video device, may provide access to devices providing different media types, or even single devices providing multiple media types. Also, some devices may provide no media types. dshow is an example encompassing all of these cases. Users should be provided with this information, so AVDeviceInfo is extended to provide it. Bump avdevice version Signed-off-by: Diederick Niehorster --- libavdevice/avdevice.c | 2 ++ libavdevice/avdevice.h | 2 ++ libavdevice/version.h | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c index 2ae26ab8e3..712ef1e80c 100644 --- a/libavdevice/avdevice.c +++ b/libavdevice/avdevice.c @@ -157,6 +157,8 @@ void avdevice_free_list_devices(AVDeviceInfoList **device_list) if (dev) { av_freep(&dev->device_name); av_freep(&dev->device_description); +if (dev->media_types) +av_freep(&dev->media_types); av_free(dev); } } diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h index 8370bbc7f2..6f24976dcc 100644 --- a/libavdevice/avdevice.h +++ b/libavdevice/avdevice.h @@ -457,6 +457,8 @@ void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContex typedef struct AVDeviceInfo { char *device_name; /**< device name, format depends on device */ char *device_description;/**< human friendly name */ +enum AVMediaType *media_types; /**< array indicating what media types(s), if any, a device can provide. If null, cannot provide any */ +int nb_media_types; /**< length of media_types array, 0 if device cannot provide any media types */ } AVDeviceInfo; /** diff --git a/libavdevice/version.h b/libavdevice/version.h index 914e156ec7..c549768e12 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVDEVICE_VERSION_MAJOR 59 -#define LIBAVDEVICE_VERSION_MINOR 0 +#define LIBAVDEVICE_VERSION_MINOR 1 #define LIBAVDEVICE_VERSION_MICRO 101 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ -- 2.28.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v4 10/13] avdevice/dshow: add media type info to get_device_list
The list returned by get_device_list now contains info about what media type(s), if any, can be provided by each device. Signed-off-by: Diederick Niehorster --- libavdevice/dshow.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index f25537db5c..fa3a06c077 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -377,6 +377,11 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, if (!device->device_name || !device->device_description) goto fail1; +device->nb_media_types = nb_media_types; +device->media_types = media_types; +nb_media_types = 0; +media_types = NULL; + // store to device_list output if (av_reallocp_array(&(*device_list)->devices, (*device_list)->nb_devices + 1, @@ -412,6 +417,8 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, av_freep(&device->device_name); if (device->device_name) av_freep(&device->device_description); +if (device->media_types) +av_freep(&device->media_types); av_free(device); } if (olestr && co_malloc) -- 2.28.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v4 11/13] fftools: provide media type info for devices
fftools now print info about what media type(s), if any, are provided by sink and source avdevices. Signed-off-by: Diederick Niehorster --- fftools/cmdutils.c | 34 -- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 3c8e5a82cd..7d7dcce2f9 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -2244,9 +2244,29 @@ double get_rotation(int32_t *displaymatrix) } #if CONFIG_AVDEVICE +static void print_device_list(const AVDeviceInfoList *device_list) +{ +// print devices +for (int i = 0; i < device_list->nb_devices; i++) { +const AVDeviceInfo *device = device_list->devices[i]; +printf("%s %s [%s] (", device_list->default_device == i ? "*" : " ", +device->device_name, device->device_description); +if (device->nb_media_types > 0 && device->media_types) { +for (int j = 0; j < device->nb_media_types; ++j) { +const char* media_type = av_get_media_type_string(device->media_types[j]); +if (j > 0) +printf(", "); +printf("%s", media_type ? media_type : "unknown"); +} +} else { +printf("none"); +} +printf(")\n"); +} +} static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) { -int ret, i; +int ret; AVDeviceInfoList *device_list = NULL; if (!fmt || !fmt->priv_class || !AV_IS_INPUT_DEVICE(fmt->priv_class->category)) @@ -2258,10 +2278,7 @@ static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) goto fail; } -for (i = 0; i < device_list->nb_devices; i++) { -printf("%c %s [%s]\n", device_list->default_device == i ? '*' : ' ', - device_list->devices[i]->device_name, device_list->devices[i]->device_description); -} +print_device_list(device_list); fail: avdevice_free_list_devices(&device_list); @@ -2270,7 +2287,7 @@ static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *opts) { -int ret, i; +int ret; AVDeviceInfoList *device_list = NULL; if (!fmt || !fmt->priv_class || !AV_IS_OUTPUT_DEVICE(fmt->priv_class->category)) @@ -2282,10 +2299,7 @@ static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *opts) goto fail; } -for (i = 0; i < device_list->nb_devices; i++) { -printf("%c %s [%s]\n", device_list->default_device == i ? '*' : ' ', - device_list->devices[i]->device_name, device_list->devices[i]->device_description); -} +print_device_list(device_list); fail: avdevice_free_list_devices(&device_list); -- 2.28.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v4 12/13] avdevice/dshow: discover source color range/space/etc
Enabled discovering a DirectShow device's color range, space, primaries, transfer characteristics and chroma location, if the device exposes that information. Sets them in the stream's codecpars. Co-authored-by: Valerii Zapodovnikov Signed-off-by: Diederick Niehorster --- libavdevice/dshow.c | 255 +++- 1 file changed, 254 insertions(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index fa3a06c077..4ad6ae102c 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -29,6 +29,31 @@ #include "libavcodec/raw.h" #include "objidl.h" #include "shlwapi.h" +// NB: technically, we should include dxva.h and use +// DXVA_ExtendedFormat, but that type is not defined in +// the MinGW headers. The DXVA2_ExtendedFormat and the +// contents of its fields is identical to +// DXVA_ExtendedFormat (see https://docs.microsoft.com/en-us/windows/win32/medfound/extended-color-information#color-space-in-media-types) +// and is provided by MinGW as well, so we use that +// instead. NB also that per the Microsoft docs, the +// lowest 8 bits of the structure, i.e. the SampleFormat +// field, contain AMCONTROL_xxx flags instead of sample +// format information, and should thus not be used. +// NB further that various values in the structure's +// fields (e.g. BT.2020 color space) are not provided +// for either of the DXVA structs, but are provided in +// the flags of the corresponding fields of Media Foundation. +// These may be provided by DirectShow devices (e.g. LAVFilters +// does so). So we use those values here too (the equivalence is +// indicated by Microsoft example code: https://docs.microsoft.com/en-us/windows/win32/api/dxva2api/ns-dxva2api-dxva2_videodesc) +typedef DWORD D3DFORMAT;// dxva2api.h header needs these types defined before include apparently in WinSDK (not MinGW). +typedef DWORD D3DPOOL; +#include "dxva2api.h" + +#ifndef AMCONTROL_COLORINFO_PRESENT +// not defined in some versions of MinGW's dvdmedia.h +# define AMCONTROL_COLORINFO_PRESENT 0x0080 // if set, indicates DXVA color info is present in the upper (24) bits of the dwControlFlags +#endif static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount) @@ -54,6 +79,192 @@ static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount) return avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), biCompression); // all others } +static enum AVColorRange dshow_color_range(DXVA2_ExtendedFormat *fmt_info) +{ +switch (fmt_info->NominalRange) +{ +case DXVA2_NominalRange_Unknown: +return AVCOL_RANGE_UNSPECIFIED; +case DXVA2_NominalRange_Normal: // equal to DXVA2_NominalRange_0_255 +return AVCOL_RANGE_JPEG; +case DXVA2_NominalRange_Wide: // equal to DXVA2_NominalRange_16_235 +return AVCOL_RANGE_MPEG; +case DXVA2_NominalRange_48_208: +// not an ffmpeg color range +return AVCOL_RANGE_UNSPECIFIED; + +// values from MediaFoundation SDK (mfobjects.h) +case 4: // MFNominalRange_64_127 +// not an ffmpeg color range +return AVCOL_RANGE_UNSPECIFIED; + +default: +return DXVA2_NominalRange_Unknown; +} +} + +static enum AVColorSpace dshow_color_space(DXVA2_ExtendedFormat *fmt_info) +{ +enum AVColorSpace ret = AVCOL_SPC_UNSPECIFIED; + +switch (fmt_info->VideoTransferMatrix) +{ +case DXVA2_VideoTransferMatrix_BT709: +ret = AVCOL_SPC_BT709; +break; +case DXVA2_VideoTransferMatrix_BT601: +ret = AVCOL_SPC_BT470BG; +break; +case DXVA2_VideoTransferMatrix_SMPTE240M: +ret = AVCOL_SPC_SMPTE240M; +break; + +// values from MediaFoundation SDK (mfobjects.h) +case 4: // MFVideoTransferMatrix_BT2020_10 +case 5: // MFVideoTransferMatrix_BT2020_12 +if (fmt_info->VideoTransferFunction==12)// MFVideoTransFunc_2020_const +ret = AVCOL_SPC_BT2020_CL; +else +ret = AVCOL_SPC_BT2020_NCL; +break; +} + +if (ret == AVCOL_SPC_UNSPECIFIED) +{ +// if color space not known from transfer matrix, +// fall back to using primaries to guess color space +switch (fmt_info->VideoPrimaries) +{ +case DXVA2_VideoPrimaries_BT709: +ret = AVCOL_SPC_BT709; +break; +case DXVA2_VideoPrimaries_BT470_2_SysM: +ret = AVCOL_SPC_FCC; +break; +case DXVA2_VideoPrimaries_BT470_2_SysBG: +case DXVA2_VideoPrimaries_EBU3213: // this is PAL +ret = AVCOL_SPC_BT470BG; +break; +case DXVA2_VideoPrimaries_SMPTE170M: +case DXVA2_VideoPrimaries_SMPTE_C: +ret = AVCOL_SPC_SMPTE170M; +break; +case DXVA2_VideoPrimaries_SMPTE240M: +ret = AVCOL_SPC_SMPTE240M; +break; +} +} + +return ret; +} + +static enum AVColorPrimaries dshow_color_prim
[FFmpeg-devel] [PATCH v4 13/13] avdevice/dshow: select format with extended color info
Some DirectShow devices (Logitech C920 webcam) expose each DirectShow format they support twice, once without and once with extended color information. During format selection, both match, this patch ensures that the format with extended color information is selected if it is available, else it falls back to a matching format without such information. This also necessitated a new code path taken for default formats of a device (when user didn't request any specific video size, etc), because the default format may be one without extended color information when a twin with extended color information is also available. Getting the extended color information when available is important as it allows setting the color space, range, primaries, transfer characteristics and chroma location of the stream provided by dshow, enabling users to get more correct color automatically out of their device. Closes: #9271 Signed-off-by: Diederick Niehorster --- libavdevice/dshow.c | 469 +++- 1 file changed, 338 insertions(+), 131 deletions(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 4ad6ae102c..6f2a3ac1ba 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -23,6 +23,7 @@ #include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" #include "libavutil/opt.h" +#include "libavutil/mem.h" #include "libavformat/internal.h" #include "libavformat/riff.h" #include "avdevice.h" @@ -690,9 +691,111 @@ error: return ret; } +static int dshow_should_set_format(AVFormatContext *avctx, enum dshowDeviceType devtype) +{ +struct dshow_ctx *ctx = avctx->priv_data; + +return (devtype == VideoDevice && (ctx->framerate || + (ctx->requested_width && ctx->requested_height) || + ctx->pixel_format != AV_PIX_FMT_NONE || + ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO)) +|| (devtype == AudioDevice && (ctx->channels || ctx->sample_size || ctx->sample_rate)); +} + + +struct dshow_format_info { +enum dshowDeviceType devtype; +// video +int64_t framerate; +enum AVPixelFormat pix_fmt; +enum AVCodecID codec_id; +enum AVColorRange col_range; +enum AVColorSpace col_space; +enum AVColorPrimaries col_prim; +enum AVColorTransferCharacteristic col_trc; +enum AVChromaLocation chroma_loc; +int width; +int height; +// audio +int sample_rate; +int sample_size; +int channels; +}; + +// user must av_free the returned pointer +static struct dshow_format_info *dshow_get_format_info(AM_MEDIA_TYPE *type) +{ +struct dshow_format_info *fmt_info = NULL; +BITMAPINFOHEADER *bih; +DXVA2_ExtendedFormat *extended_format_info = NULL; +WAVEFORMATEX *fx; +enum dshowDeviceType devtype; +int64_t framerate; + +if (!type) +return NULL; + +if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) { +VIDEOINFOHEADER *v = (void *) type->pbFormat; +framerate = v->AvgTimePerFrame; +bih = &v->bmiHeader; +devtype = VideoDevice; +} else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) { +VIDEOINFOHEADER2 *v = (void *) type->pbFormat; +devtype = VideoDevice; +framerate = v->AvgTimePerFrame; +bih = &v->bmiHeader; +if (v->dwControlFlags & AMCONTROL_COLORINFO_PRESENT) +extended_format_info = (DXVA2_ExtendedFormat *) &v->dwControlFlags; +} else if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) { +fx = (void *) type->pbFormat; +devtype = AudioDevice; +} else { +return NULL; +} + +fmt_info = av_mallocz(sizeof(struct dshow_format_info)); +if (!fmt_info) +return NULL; +// initialize fields where unset is not zero +fmt_info->pix_fmt = AV_PIX_FMT_NONE; +fmt_info->col_space = AVCOL_SPC_UNSPECIFIED; +fmt_info->col_prim = AVCOL_PRI_UNSPECIFIED; +fmt_info->col_trc = AVCOL_TRC_UNSPECIFIED; +// now get info about format +fmt_info->devtype = devtype; +if (devtype == VideoDevice) { +fmt_info->width = bih->biWidth; +fmt_info->height = bih->biHeight; +fmt_info->framerate = framerate; +fmt_info->pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount); +if (fmt_info->pix_fmt == AV_PIX_FMT_NONE) { +const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL }; +fmt_info->codec_id = av_codec_get_id(tags, bih->biCompression); +} +else +fmt_info->codec_id = AV_CODEC_ID_RAWVIDEO; + +if (extended_format_info) { +fmt_info->col_range = dshow_color_range(extended_format_info); +fmt_info->col_space = dshow_color_space(extended_format_info); +fmt_info->col_prim = dshow_color_primaries(extended_format_info); +fmt_info->col_trc = dshow_color_trc(extended