From 4be85c9331ca7c3360dffbbd4ce5055e8c478d2e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 3 Jan 2022 22:10:46 +0100 Subject: [PATCH 01/38] lib*/version.h: Bump Versions after release/5.0 branch Signed-off-by: Michael Niedermayer --- libavcodec/version.h | 2 +- libavdevice/version.h | 2 +- libavfilter/version.h | 2 +- libavformat/version.h | 2 +- libavutil/version.h | 2 +- libpostproc/version.h | 2 +- libswresample/version.h | 2 +- libswscale/version.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index e2499b505b..7a8852bf15 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 59 -#define LIBAVCODEC_VERSION_MINOR 16 +#define LIBAVCODEC_VERSION_MINOR 17 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavdevice/version.h b/libavdevice/version.h index 56a0fa5c6c..add4d4228a 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 2 +#define LIBAVDEVICE_VERSION_MINOR 3 #define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ diff --git a/libavfilter/version.h b/libavfilter/version.h index d17abdc5fa..c76f6d22e2 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 22 +#define LIBAVFILTER_VERSION_MINOR 23 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavformat/version.h b/libavformat/version.h index 2b51351ccb..e8873c8925 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 14 +#define LIBAVFORMAT_VERSION_MINOR 15 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavutil/version.h b/libavutil/version.h index 318045d4c4..ca5d34d681 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 14 +#define LIBAVUTIL_VERSION_MINOR 15 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libpostproc/version.h b/libpostproc/version.h index 6dd0b1bcc2..33fd0479b1 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBPOSTPROC_VERSION_MAJOR 56 -#define LIBPOSTPROC_VERSION_MINOR 1 +#define LIBPOSTPROC_VERSION_MINOR 2 #define LIBPOSTPROC_VERSION_MICRO 100 #define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \ diff --git a/libswresample/version.h b/libswresample/version.h index 36220ebe7b..1a786c6a1d 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBSWRESAMPLE_VERSION_MAJOR 4 -#define LIBSWRESAMPLE_VERSION_MINOR 1 +#define LIBSWRESAMPLE_VERSION_MINOR 2 #define LIBSWRESAMPLE_VERSION_MICRO 100 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ diff --git a/libswscale/version.h b/libswscale/version.h index e5270811fb..aaaf6edc32 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -27,7 +27,7 @@ #include "libavutil/version.h" #define LIBSWSCALE_VERSION_MAJOR 6 -#define LIBSWSCALE_VERSION_MINOR 2 +#define LIBSWSCALE_VERSION_MINOR 3 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ From 76e062322c3527b76b9b180ff0caa52b7af4784b Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 11 Dec 2021 16:27:28 +0100 Subject: [PATCH 02/38] avformat/movenc: factorize data shifting And move data shift function from movenc to utils. Signed-off-by: Marton Balint --- libavformat/internal.h | 7 ++++++ libavformat/movenc.c | 55 ++--------------------------------------- libavformat/utils.c | 56 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 53 deletions(-) diff --git a/libavformat/internal.h b/libavformat/internal.h index 2ba795d669..63235ce5cf 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -1019,4 +1019,11 @@ void ff_format_set_url(AVFormatContext *s, char *url); void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]); +/** + * Make shift_size amount of space at read_start by shifting data in the output + * at read_start until the current IO position. The underlying IO context must + * be seekable. + */ +int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size); + #endif /* AVFORMAT_INTERNAL_H */ diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 0f912dd012..40ad4f8642 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -7150,13 +7150,8 @@ static int compute_sidx_size(AVFormatContext *s) static int shift_data(AVFormatContext *s) { - int ret = 0, moov_size; + int moov_size; MOVMuxContext *mov = s->priv_data; - int64_t pos, pos_end; - uint8_t *buf, *read_buf[2]; - int read_buf_id = 0; - int read_size[2]; - AVIOContext *read_pb; if (mov->flags & FF_MOV_FLAG_FRAGMENT) moov_size = compute_sidx_size(s); @@ -7165,53 +7160,7 @@ static int shift_data(AVFormatContext *s) if (moov_size < 0) return moov_size; - buf = av_malloc(moov_size * 2); - if (!buf) - return AVERROR(ENOMEM); - read_buf[0] = buf; - read_buf[1] = buf + moov_size; - - /* Shift the data: the AVIO context of the output can only be used for - * writing, so we re-open the same output, but for reading. It also avoids - * a read/seek/write/seek back and forth. */ - avio_flush(s->pb); - ret = s->io_open(s, &read_pb, s->url, AVIO_FLAG_READ, NULL); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for " - "the second pass (faststart)\n", s->url); - goto end; - } - - /* mark the end of the shift to up to the last data we wrote, and get ready - * for writing */ - pos_end = avio_tell(s->pb); - avio_seek(s->pb, mov->reserved_header_pos + moov_size, SEEK_SET); - - /* start reading at where the new moov will be placed */ - avio_seek(read_pb, mov->reserved_header_pos, SEEK_SET); - pos = avio_tell(read_pb); - -#define READ_BLOCK do { \ - read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], moov_size); \ - read_buf_id ^= 1; \ -} while (0) - - /* shift data by chunk of at most moov_size */ - READ_BLOCK; - do { - int n; - READ_BLOCK; - n = read_size[read_buf_id]; - if (n <= 0) - break; - avio_write(s->pb, read_buf[read_buf_id], n); - pos += n; - } while (pos < pos_end); - ff_format_io_close(s, &read_pb); - -end: - av_free(buf); - return ret; + return ff_format_shift_data(s, mov->reserved_header_pos, moov_size); } static int mov_write_trailer(AVFormatContext *s) diff --git a/libavformat/utils.c b/libavformat/utils.c index 332ba534d2..a78797ef57 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2035,3 +2035,59 @@ const char *av_disposition_to_string(int disposition) return NULL; } + +int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size) +{ + int ret; + int64_t pos, pos_end; + uint8_t *buf, *read_buf[2]; + int read_buf_id = 0; + int read_size[2]; + AVIOContext *read_pb; + + buf = av_malloc_array(shift_size, 2); + if (!buf) + return AVERROR(ENOMEM); + read_buf[0] = buf; + read_buf[1] = buf + shift_size; + + /* Shift the data: the AVIO context of the output can only be used for + * writing, so we re-open the same output, but for reading. It also avoids + * a read/seek/write/seek back and forth. */ + avio_flush(s->pb); + ret = s->io_open(s, &read_pb, s->url, AVIO_FLAG_READ, NULL); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for shifting data\n", s->url); + goto end; + } + + /* mark the end of the shift to up to the last data we wrote, and get ready + * for writing */ + pos_end = avio_tell(s->pb); + avio_seek(s->pb, read_start + shift_size, SEEK_SET); + + avio_seek(read_pb, read_start, SEEK_SET); + pos = avio_tell(read_pb); + +#define READ_BLOCK do { \ + read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], shift_size); \ + read_buf_id ^= 1; \ +} while (0) + + /* shift data by chunk of at most shift_size */ + READ_BLOCK; + do { + int n; + READ_BLOCK; + n = read_size[read_buf_id]; + if (n <= 0) + break; + avio_write(s->pb, read_buf[read_buf_id], n); + pos += n; + } while (pos < pos_end); + ff_format_io_close(s, &read_pb); + +end: + av_free(buf); + return ret; +} From 10a0a8ca8339589f32e8402f20d054c8bba8c3ff Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 11 Dec 2021 19:00:06 +0100 Subject: [PATCH 03/38] avformat/flvenc: use ff_format_shift_data for data shifting add_keyframe_index seems to generate a corrupted index even before this change. Signed-off-by: Marton Balint --- libavformat/flvenc.c | 59 +++++--------------------------------------- 1 file changed, 6 insertions(+), 53 deletions(-) diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 5130d429ad..31d1d93c23 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -576,15 +576,9 @@ static int flv_append_keyframe_info(AVFormatContext *s, FLVContext *flv, double static int shift_data(AVFormatContext *s) { - int ret = 0; - int n = 0; + int ret; int64_t metadata_size = 0; FLVContext *flv = s->priv_data; - int64_t pos, pos_end = avio_tell(s->pb); /* Save the pre-shift size. */ - uint8_t *buf, *read_buf[2]; - int read_buf_id = 0; - int read_size[2]; - AVIOContext *read_pb; metadata_size = flv->filepositions_count * 9 * 2 + 10; /* filepositions and times value */ metadata_size += 2 + 13; /* filepositions String */ @@ -596,58 +590,17 @@ static int shift_data(AVFormatContext *s) if (metadata_size < 0) return metadata_size; - buf = av_malloc_array(metadata_size, 2); - if (!buf) { - return AVERROR(ENOMEM); - } - read_buf[0] = buf; - read_buf[1] = buf + metadata_size; + ret = ff_format_shift_data(s, flv->keyframes_info_offset, metadata_size); + if (ret < 0) + return ret; avio_seek(s->pb, flv->metadata_size_pos, SEEK_SET); avio_wb24(s->pb, flv->metadata_totalsize + metadata_size); - avio_seek(s->pb, flv->metadata_totalsize_pos, SEEK_SET); + avio_seek(s->pb, flv->metadata_totalsize_pos + metadata_size, SEEK_SET); avio_wb32(s->pb, flv->metadata_totalsize + 11 + metadata_size); - /* Shift the data: the AVIO context of the output can only be used for - * writing, so we re-open the same output, but for reading. It also avoids - * a read/seek/write/seek back and forth. */ - avio_flush(s->pb); - ret = s->io_open(s, &read_pb, s->url, AVIO_FLAG_READ, NULL); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for " - "the second pass (add_keyframe_index)\n", s->url); - goto end; - } - - /* Get ready for writing. */ - avio_seek(s->pb, flv->keyframes_info_offset + metadata_size, SEEK_SET); - - /* start reading at where the keyframe index information will be placed */ - avio_seek(read_pb, flv->keyframes_info_offset, SEEK_SET); - pos = avio_tell(read_pb); - -#define READ_BLOCK do { \ - read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], metadata_size); \ - read_buf_id ^= 1; \ -} while (0) - - /* shift data by chunk of at most keyframe *filepositions* and *times* size */ - READ_BLOCK; - do { - READ_BLOCK; - n = read_size[read_buf_id]; - if (n < 0) - break; - avio_write(s->pb, read_buf[read_buf_id], n); - pos += n; - } while (pos <= pos_end); - - ff_format_io_close(s, &read_pb); - -end: - av_free(buf); - return ret; + return 0; } static int flv_init(struct AVFormatContext *s) From 26d6c81dc6ed205005dd34f837f52569c1cb3903 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 11 Dec 2021 19:28:50 +0100 Subject: [PATCH 04/38] avformat/segafilmenc: use ff_format_shift_data for shifting Signed-off-by: Marton Balint --- libavformat/segafilmenc.c | 49 ++++----------------------------------- 1 file changed, 4 insertions(+), 45 deletions(-) diff --git a/libavformat/segafilmenc.c b/libavformat/segafilmenc.c index ff8cb66aca..737805faa6 100644 --- a/libavformat/segafilmenc.c +++ b/libavformat/segafilmenc.c @@ -170,54 +170,13 @@ static int film_init(AVFormatContext *format_context) static int write_header(AVFormatContext *format_context, uint8_t *header, unsigned header_size) { - int ret = 0; - int64_t pos, pos_end; - uint8_t *buf, *read_buf[2]; - int read_buf_id = 0; - int read_size[2]; - AVIOContext *read_pb; - - buf = av_malloc(header_size); - if (!buf) - return AVERROR(ENOMEM); - read_buf[0] = buf; - read_buf[1] = header; - read_size[1] = header_size; - - /* Write the header at the beginning of the file, shifting all content as necessary; - * based on the approach used by MOV faststart. */ - avio_flush(format_context->pb); - ret = format_context->io_open(format_context, &read_pb, format_context->url, AVIO_FLAG_READ, NULL); - if (ret < 0) { - av_log(format_context, AV_LOG_ERROR, "Unable to re-open %s output file to " - "write the header\n", format_context->url); - av_free(buf); + int ret = ff_format_shift_data(format_context, 0, header_size); + if (ret < 0) return ret; - } - /* Mark the end of the shift to up to the last data we are going to write, - * and get ready for writing */ - pos_end = avio_tell(format_context->pb) + header_size; - pos = avio_seek(format_context->pb, 0, SEEK_SET); + avio_seek(format_context->pb, 0, SEEK_SET); + avio_write(format_context->pb, header, header_size); - /* start reading at where the new header will be placed */ - avio_seek(read_pb, 0, SEEK_SET); - - /* shift data by chunk of at most header_size */ - do { - int n; - read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], - header_size); - read_buf_id ^= 1; - n = read_size[read_buf_id]; - if (n <= 0) - break; - avio_write(format_context->pb, read_buf[read_buf_id], n); - pos += n; - } while (pos < pos_end); - ff_format_io_close(format_context, &read_pb); - - av_free(buf); return 0; } From 573b6b8a607398c5f34108efda9c29d41c5727ff Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 11 Dec 2021 19:30:59 +0100 Subject: [PATCH 05/38] avformat/utils: propagate return value of ff_format_io_close in ff_format_shift_data Signed-off-by: Marton Balint --- libavformat/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index a78797ef57..23e81bda9d 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2085,7 +2085,7 @@ int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size) avio_write(s->pb, read_buf[read_buf_id], n); pos += n; } while (pos < pos_end); - ff_format_io_close(s, &read_pb); + ret = ff_format_io_close(s, &read_pb); end: av_free(buf); From 5c16e463745ece2f18777a5424d7779853d63011 Mon Sep 17 00:00:00 2001 From: quietvoid Date: Sat, 1 Jan 2022 17:51:49 +0100 Subject: [PATCH 06/38] avformat/dovi_isom: Implement Dolby Vision configuration parsing/writing Both parse/write implementations are based on mov/movenc. This only adds support for the "Dolby Vision configuration box". Other configuration boxes, such as "Dolby Vision enhancement layer configuration box" are not supported. The new functions will be used to implement parsing/writing the DOVI config for Matroska, as well as to refactor both mov/movenc to use dovi_isom functions. Signed-off-by: quietvoid Signed-off-by: Andreas Rheinhardt --- libavformat/dovi_isom.c | 118 ++++++++++++++++++++++++++++++++++++++++ libavformat/dovi_isom.h | 35 ++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 libavformat/dovi_isom.c create mode 100644 libavformat/dovi_isom.h diff --git a/libavformat/dovi_isom.c b/libavformat/dovi_isom.c new file mode 100644 index 0000000000..76681b9451 --- /dev/null +++ b/libavformat/dovi_isom.c @@ -0,0 +1,118 @@ +/* + * DOVI ISO Media common code + * + * Copyright (c) 2020 Vacing Fang + * Copyright (c) 2021 quietvoid + * + * 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/dovi_meta.h" + +#include "libavcodec/put_bits.h" + +#include "avformat.h" +#include "dovi_isom.h" + +int ff_isom_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const uint8_t *buf_ptr, uint64_t size) +{ + uint32_t buf; + AVDOVIDecoderConfigurationRecord *dovi; + size_t dovi_size; + int ret; + + if (size > (1 << 30) || size < 4) + return AVERROR_INVALIDDATA; + + dovi = av_dovi_alloc(&dovi_size); + if (!dovi) + return AVERROR(ENOMEM); + + dovi->dv_version_major = *buf_ptr++; // 8 bits + dovi->dv_version_minor = *buf_ptr++; // 8 bits + + buf = *buf_ptr++ << 8; + buf |= *buf_ptr++; + + dovi->dv_profile = (buf >> 9) & 0x7f; // 7 bits + dovi->dv_level = (buf >> 3) & 0x3f; // 6 bits + dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit + dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit + dovi->bl_present_flag = buf & 0x01; // 1 bit + + // Has enough remaining data + if (size >= 5) { + dovi->dv_bl_signal_compatibility_id = ((*buf_ptr++) >> 4) & 0x0f; // 4 bits + } else { + // 0 stands for None + // Dolby Vision V1.2.93 profiles and levels + dovi->dv_bl_signal_compatibility_id = 0; + } + + ret = av_stream_add_side_data(st, AV_PKT_DATA_DOVI_CONF, + (uint8_t *)dovi, dovi_size); + if (ret < 0) { + av_free(dovi); + return ret; + } + + av_log(s, AV_LOG_TRACE, "DOVI in dvcC/dvvC/dvwC box, version: %d.%d, profile: %d, level: %d, " + "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", + dovi->dv_version_major, dovi->dv_version_minor, + dovi->dv_profile, dovi->dv_level, + dovi->rpu_present_flag, + dovi->el_present_flag, + dovi->bl_present_flag, + dovi->dv_bl_signal_compatibility_id); + + return 0; +} + +void ff_isom_put_dvcc_dvvc(AVFormatContext *s, uint8_t out[ISOM_DVCC_DVVC_SIZE], + AVDOVIDecoderConfigurationRecord *dovi) +{ + PutBitContext pb; + + init_put_bits(&pb, out, ISOM_DVCC_DVVC_SIZE); + + put_bits(&pb, 8, dovi->dv_version_major); + put_bits(&pb, 8, dovi->dv_version_minor); + put_bits(&pb, 7, dovi->dv_profile & 0x7f); + put_bits(&pb, 6, dovi->dv_level & 0x3f); + put_bits(&pb, 1, !!dovi->rpu_present_flag); + put_bits(&pb, 1, !!dovi->el_present_flag); + put_bits(&pb, 1, !!dovi->bl_present_flag); + put_bits(&pb, 4, dovi->dv_bl_signal_compatibility_id & 0x0f); + + put_bits(&pb, 28, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + + flush_put_bits(&pb); + + av_log(s, AV_LOG_DEBUG, "DOVI in %s box, version: %d.%d, profile: %d, level: %d, " + "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", + dovi->dv_profile > 10 ? "dvwC" : (dovi->dv_profile > 7 ? "dvvC" : "dvcC"), + dovi->dv_version_major, dovi->dv_version_minor, + dovi->dv_profile, dovi->dv_level, + dovi->rpu_present_flag, + dovi->el_present_flag, + dovi->bl_present_flag, + dovi->dv_bl_signal_compatibility_id); +} diff --git a/libavformat/dovi_isom.h b/libavformat/dovi_isom.h new file mode 100644 index 0000000000..1526164319 --- /dev/null +++ b/libavformat/dovi_isom.h @@ -0,0 +1,35 @@ +/* + * DOVI ISO Media common code + * Copyright (c) 2021 quietvoid + * + * 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 + */ + +#ifndef AVFORMAT_DOVI_ISOM_H +#define AVFORMAT_DOVI_ISOM_H + +#include "libavutil/dovi_meta.h" + +#include "avformat.h" + +#define ISOM_DVCC_DVVC_SIZE 24 + +int ff_isom_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const uint8_t *buf_ptr, uint64_t size); +void ff_isom_put_dvcc_dvvc(AVFormatContext *s, uint8_t out[ISOM_DVCC_DVVC_SIZE], + AVDOVIDecoderConfigurationRecord *dovi); + +#endif /* AVFORMAT_DOVI_ISOM_H */ From 05c07943b04de2514343b1de09dc6dca64502643 Mon Sep 17 00:00:00 2001 From: quietvoid Date: Sat, 1 Jan 2022 17:51:50 +0100 Subject: [PATCH 07/38] avformat/matroska{dec, enc}: Parse BlockAdditionMapping elements Adds handling of dvcC/dvvC block addition mappings. The parsing creates AVDOVIDecoderConfigurationRecord side data. The configuration block is written when muxing into Matroska, if DOVI side data is present for the track. Most of the Matroska element parsing is based on Plex's FFmpeg source code. Signed-off-by: quietvoid Signed-off-by: Andreas Rheinhardt --- libavformat/Makefile | 4 +-- libavformat/matroska.h | 9 ++++++ libavformat/matroskadec.c | 58 +++++++++++++++++++++++++++++++++++++-- libavformat/matroskaenc.c | 37 +++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 4 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index e31b248ac0..4464c2b049 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -316,11 +316,11 @@ OBJS-$(CONFIG_M4V_MUXER) += rawenc.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \ flac_picture.o isom_tags.o rmsipr.o \ oggparsevorbis.o vorbiscomment.o \ - qtpalette.o replaygain.o + qtpalette.o replaygain.o dovi_isom.o OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \ av1.o avc.o hevc.o isom_tags.o \ flacenc_header.o avlanguage.o \ - vorbiscomment.o wv.o + vorbiscomment.o wv.o dovi_isom.o OBJS-$(CONFIG_MCA_DEMUXER) += mca.o OBJS-$(CONFIG_MCC_DEMUXER) += mccdec.o subtitles.o OBJS-$(CONFIG_MD5_MUXER) += hashenc.o diff --git a/libavformat/matroska.h b/libavformat/matroska.h index 2d04a6838b..16491aae22 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -111,6 +111,7 @@ #define MATROSKA_ID_TRACKCONTENTENCODING 0x6240 #define MATROSKA_ID_TRACKTIMECODESCALE 0x23314F #define MATROSKA_ID_TRACKMAXBLKADDID 0x55EE +#define MATROSKA_ID_TRACKBLKADDMAPPING 0x41E4 /* IDs in the trackvideo master */ #define MATROSKA_ID_VIDEOFRAMERATE 0x2383E3 @@ -189,6 +190,12 @@ #define MATROSKA_ID_ENCODINGSIGKEYID 0x47E4 #define MATROSKA_ID_ENCODINGSIGNATURE 0x47E3 +/* IDs in the block addition mapping master */ +#define MATROSKA_ID_BLKADDIDVALUE 0x41F0 +#define MATROSKA_ID_BLKADDIDNAME 0x41A4 +#define MATROSKA_ID_BLKADDIDTYPE 0x41E7 +#define MATROSKA_ID_BLKADDIDEXTRADATA 0x41ED + /* ID in the cues master */ #define MATROSKA_ID_POINTENTRY 0xBB @@ -385,4 +392,6 @@ extern const char * const ff_matroska_video_stereo_plane[MATROSKA_VIDEO_STEREO_P int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode); +#define DVCC_DVVC_BLOCK_TYPE_NAME "Dolby Vision configuration" + #endif /* AVFORMAT_MATROSKA_H */ diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index a4bbbe954e..6ce553205d 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -53,6 +53,7 @@ #include "avformat.h" #include "avio_internal.h" +#include "dovi_isom.h" #include "internal.h" #include "isom.h" #include "matroska.h" @@ -239,6 +240,13 @@ typedef struct MatroskaTrackOperation { EbmlList combine_planes; } MatroskaTrackOperation; +typedef struct MatroskaBlockAdditionMapping { + uint64_t value; + char *name; + uint64_t type; + EbmlBin extradata; +} MatroskaBlockAdditionMapping; + typedef struct MatroskaTrack { uint64_t num; uint64_t uid; @@ -269,6 +277,7 @@ typedef struct MatroskaTrack { int ms_compat; int needs_decoding; uint64_t max_block_additional_id; + EbmlList block_addition_mappings; uint32_t palette[AVPALETTE_COUNT]; int has_palette; @@ -419,8 +428,8 @@ typedef struct MatroskaDemuxContext { // incomplete type (6.7.2 in C90, 6.9.2 in C99). // Removing the sizes breaks MSVC. static EbmlSyntax ebml_syntax[3], matroska_segment[9], matroska_track_video_color[15], matroska_track_video[19], - matroska_track[32], matroska_track_encoding[6], matroska_track_encodings[2], - matroska_track_combine_planes[2], matroska_track_operation[2], matroska_tracks[2], + matroska_track[33], matroska_track_encoding[6], matroska_track_encodings[2], + matroska_track_combine_planes[2], matroska_track_operation[2], matroska_block_addition_mapping[5], matroska_tracks[2], matroska_attachments[2], matroska_chapter_entry[9], matroska_chapter[6], matroska_chapters[2], matroska_index_entry[3], matroska_index[2], matroska_tag[3], matroska_tags[2], matroska_seekhead[2], matroska_blockadditions[2], matroska_blockgroup[8], matroska_cluster_parsing[8]; @@ -570,6 +579,14 @@ static EbmlSyntax matroska_track_operation[] = { CHILD_OF(matroska_track) }; +static EbmlSyntax matroska_block_addition_mapping[] = { + { MATROSKA_ID_BLKADDIDVALUE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, value) }, + { MATROSKA_ID_BLKADDIDNAME, EBML_STR, 0, 0, offsetof(MatroskaBlockAdditionMapping, name) }, + { MATROSKA_ID_BLKADDIDTYPE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, type) }, + { MATROSKA_ID_BLKADDIDEXTRADATA, EBML_BIN, 0, 0, offsetof(MatroskaBlockAdditionMapping, extradata) }, + CHILD_OF(matroska_track) +}; + static EbmlSyntax matroska_track[] = { { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, 0, offsetof(MatroskaTrack, num) }, { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, 0, offsetof(MatroskaTrack, name) }, @@ -593,6 +610,7 @@ static EbmlSyntax matroska_track[] = { { MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, 0, offsetof(MatroskaTrack, operation), { .n = matroska_track_operation } }, { MATROSKA_ID_TRACKCONTENTENCODINGS, EBML_NEST, 0, 0, 0, { .n = matroska_track_encodings } }, { MATROSKA_ID_TRACKMAXBLKADDID, EBML_UINT, 0, 0, offsetof(MatroskaTrack, max_block_additional_id), { .u = 0 } }, + { MATROSKA_ID_TRACKBLKADDMAPPING, EBML_NEST, 0, sizeof(MatroskaBlockAdditionMapping), offsetof(MatroskaTrack, block_addition_mappings), { .n = matroska_block_addition_mapping } }, { MATROSKA_ID_SEEKPREROLL, EBML_UINT, 0, 0, offsetof(MatroskaTrack, seek_preroll), { .u = 0 } }, { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE }, { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE }, @@ -2311,6 +2329,38 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track, return 0; } +static int mkv_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const MatroskaTrack *track, + EbmlBin *bin) +{ + return ff_isom_parse_dvcc_dvvc(s, st, bin->data, bin->size); +} + +static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, const MatroskaTrack *track) +{ + const EbmlList *mappings_list = &track->block_addition_mappings; + MatroskaBlockAdditionMapping *mappings = mappings_list->elem; + int ret; + + for (int i = 0; i < mappings_list->nb_elem; i++) { + MatroskaBlockAdditionMapping *mapping = &mappings[i]; + + switch (mapping->type) { + case MKBETAG('d','v','c','C'): + case MKBETAG('d','v','v','C'): + if ((ret = mkv_parse_dvcc_dvvc(s, st, track, &mapping->extradata)) < 0) + return ret; + + break; + default: + av_log(s, AV_LOG_DEBUG, + "Unknown block additional mapping type 0x%"PRIx64", value %"PRIu64", name \"%s\"\n", + mapping->type, mapping->value, mapping->name ? mapping->name : ""); + } + } + + return 0; +} + static int get_qt_codec(MatroskaTrack *track, uint32_t *fourcc, enum AVCodecID *codec_id) { const AVCodecTag *codec_tags; @@ -2898,6 +2948,10 @@ static int matroska_parse_tracks(AVFormatContext *s) if (track->flag_textdescriptions) st->disposition |= AV_DISPOSITION_DESCRIPTIONS; } + + ret = mkv_parse_block_addition_mappings(s, st, track); + if (ret < 0) + return ret; } return 0; diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 8c4cf4024a..5cc59dc9f8 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -27,6 +27,7 @@ #include "avformat.h" #include "avio_internal.h" #include "avlanguage.h" +#include "dovi_isom.h" #include "flacenc.h" #include "internal.h" #include "isom.h" @@ -1120,6 +1121,37 @@ static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, return 0; } +static void mkv_write_dovi(AVFormatContext *s, AVIOContext *pb, AVStream *st) +{ + AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *) + av_stream_get_side_data(st, AV_PKT_DATA_DOVI_CONF, NULL); + + if (dovi && dovi->dv_profile <= 10) { + ebml_master mapping; + uint8_t buf[ISOM_DVCC_DVVC_SIZE]; + uint32_t type; + + uint64_t expected_size = (2 + 1 + (sizeof(DVCC_DVVC_BLOCK_TYPE_NAME) - 1)) + + (2 + 1 + 4) + (2 + 1 + ISOM_DVCC_DVVC_SIZE); + + if (dovi->dv_profile > 7) { + type = MKBETAG('d', 'v', 'v', 'C'); + } else { + type = MKBETAG('d', 'v', 'c', 'C'); + } + + ff_isom_put_dvcc_dvvc(s, buf, dovi); + + mapping = start_ebml_master(pb, MATROSKA_ID_TRACKBLKADDMAPPING, expected_size); + + put_ebml_string(pb, MATROSKA_ID_BLKADDIDNAME, DVCC_DVVC_BLOCK_TYPE_NAME); + put_ebml_uint(pb, MATROSKA_ID_BLKADDIDTYPE, type); + put_ebml_binary(pb, MATROSKA_ID_BLKADDIDEXTRADATA, buf, sizeof(buf)); + + end_ebml_master(pb, mapping); + } +} + static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, AVStream *st, mkv_track *track, AVIOContext *pb, int is_default) @@ -1319,6 +1351,11 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, mkv_write_video_projection(s, pb, st); end_ebml_master(pb, subinfo); + + if (mkv->mode != MODE_WEBM) { + mkv_write_dovi(s, pb, st); + } + break; case AVMEDIA_TYPE_AUDIO: From 9906f9ae3b678d95b413dd4320e334ea3e2cf70a Mon Sep 17 00:00:00 2001 From: quietvoid Date: Sat, 1 Jan 2022 17:51:51 +0100 Subject: [PATCH 08/38] avformat/mov: Refactor mov_read_dvcc_dvvc to use ff_isom_parse_dvcc_dvvc To avoid duplicating code. The implementation in dovi_isom is identical. Signed-off-by: quietvoid Signed-off-by: Andreas Rheinhardt --- libavformat/Makefile | 2 +- libavformat/mov.c | 50 +++++++------------------------------------- 2 files changed, 8 insertions(+), 44 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index 4464c2b049..cd9810ba01 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -339,7 +339,7 @@ OBJS-$(CONFIG_MMF_MUXER) += mmf.o rawenc.o OBJS-$(CONFIG_MODS_DEMUXER) += mods.o OBJS-$(CONFIG_MOFLEX_DEMUXER) += moflex.o OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o mov_esds.o \ - qtpalette.o replaygain.o + qtpalette.o replaygain.o dovi_isom.o OBJS-$(CONFIG_MOV_MUXER) += movenc.o av1.o avc.o hevc.o vpcc.o \ movenchint.o mov_chan.o rtp.o \ movenccenc.o movenc_ttml.o rawutils.o diff --git a/libavformat/mov.c b/libavformat/mov.c index 351ecde770..ad5ab6b491 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -55,6 +55,7 @@ #include "avformat.h" #include "internal.h" #include "avio_internal.h" +#include "dovi_isom.h" #include "riff.h" #include "isom.h" #include "libavcodec/get_bits.h" @@ -7062,58 +7063,21 @@ static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; - uint32_t buf; - AVDOVIDecoderConfigurationRecord *dovi; - size_t dovi_size; + uint8_t buf[ISOM_DVCC_DVVC_SIZE]; int ret; + int64_t read_size = atom.size; if (c->fc->nb_streams < 1) return 0; st = c->fc->streams[c->fc->nb_streams-1]; - if ((uint64_t)atom.size > (1<<30) || atom.size < 4) - return AVERROR_INVALIDDATA; + // At most 24 bytes + read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE); - dovi = av_dovi_alloc(&dovi_size); - if (!dovi) - return AVERROR(ENOMEM); - - dovi->dv_version_major = avio_r8(pb); - dovi->dv_version_minor = avio_r8(pb); - - buf = avio_rb16(pb); - dovi->dv_profile = (buf >> 9) & 0x7f; // 7 bits - dovi->dv_level = (buf >> 3) & 0x3f; // 6 bits - dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit - dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit - dovi->bl_present_flag = buf & 0x01; // 1 bit - if (atom.size >= 24) { // 4 + 4 + 4 * 4 - buf = avio_r8(pb); - dovi->dv_bl_signal_compatibility_id = (buf >> 4) & 0x0f; // 4 bits - } else { - // 0 stands for None - // Dolby Vision V1.2.93 profiles and levels - dovi->dv_bl_signal_compatibility_id = 0; - } - - ret = av_stream_add_side_data(st, AV_PKT_DATA_DOVI_CONF, - (uint8_t *)dovi, dovi_size); - if (ret < 0) { - av_free(dovi); + if ((ret = ffio_read_size(pb, buf, read_size)) < 0) return ret; - } - av_log(c, AV_LOG_TRACE, "DOVI in dvcC/dvvC/dvwC box, version: %d.%d, profile: %d, level: %d, " - "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", - dovi->dv_version_major, dovi->dv_version_minor, - dovi->dv_profile, dovi->dv_level, - dovi->rpu_present_flag, - dovi->el_present_flag, - dovi->bl_present_flag, - dovi->dv_bl_signal_compatibility_id - ); - - return 0; + return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size); } static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom) From f0fb005f59f6febcf2ffc8140bdb7f136ac56add Mon Sep 17 00:00:00 2001 From: quietvoid Date: Sat, 1 Jan 2022 17:51:52 +0100 Subject: [PATCH 09/38] avformat/movenc: Refactor mov_write_dvcc_dvvc_tag to use ff_isom_put_dvcc_dvvc Improves code legibility by not using bit shifts. Also avoids duplicating the dvcC/dvvC ISOM box writing code. Signed-off-by: quietvoid Signed-off-by: Andreas Rheinhardt --- libavformat/Makefile | 3 ++- libavformat/movenc.c | 22 ++++++---------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index cd9810ba01..a9afb9c042 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -342,7 +342,8 @@ OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o mov_esds.o \ qtpalette.o replaygain.o dovi_isom.o OBJS-$(CONFIG_MOV_MUXER) += movenc.o av1.o avc.o hevc.o vpcc.o \ movenchint.o mov_chan.o rtp.o \ - movenccenc.o movenc_ttml.o rawutils.o + movenccenc.o movenc_ttml.o rawutils.o \ + dovi_isom.o OBJS-$(CONFIG_MP2_MUXER) += rawenc.o OBJS-$(CONFIG_MP3_DEMUXER) += mp3dec.o replaygain.o OBJS-$(CONFIG_MP3_MUXER) += mp3enc.o rawenc.o id3v2enc.o diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 40ad4f8642..04cf2f777d 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -27,6 +27,7 @@ #include "movenc.h" #include "avformat.h" #include "avio_internal.h" +#include "dovi_isom.h" #include "riff.h" #include "avio.h" #include "isom.h" @@ -1911,6 +1912,8 @@ static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMa static int mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDecoderConfigurationRecord *dovi) { + uint8_t buf[ISOM_DVCC_DVVC_SIZE]; + avio_wb32(pb, 32); /* size = 8 + 24 */ if (dovi->dv_profile > 10) ffio_wfourcc(pb, "dvwC"); @@ -1918,23 +1921,10 @@ static int mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDe ffio_wfourcc(pb, "dvvC"); else ffio_wfourcc(pb, "dvcC"); - avio_w8(pb, dovi->dv_version_major); - avio_w8(pb, dovi->dv_version_minor); - avio_wb16(pb, (dovi->dv_profile << 9) | (dovi->dv_level << 3) | - (dovi->rpu_present_flag << 2) | (dovi->el_present_flag << 1) | - dovi->bl_present_flag); - avio_wb32(pb, (dovi->dv_bl_signal_compatibility_id << 28) | 0); - ffio_fill(pb, 0, 4 * 4); /* reserved */ - av_log(s, AV_LOG_DEBUG, "DOVI in %s box, version: %d.%d, profile: %d, level: %d, " - "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", - dovi->dv_profile > 10 ? "dvwC" : (dovi->dv_profile > 7 ? "dvvC" : "dvcC"), - dovi->dv_version_major, dovi->dv_version_minor, - dovi->dv_profile, dovi->dv_level, - dovi->rpu_present_flag, - dovi->el_present_flag, - dovi->bl_present_flag, - dovi->dv_bl_signal_compatibility_id); + ff_isom_put_dvcc_dvvc(s, buf, dovi); + avio_write(pb, buf, sizeof(buf)); + return 32; /* 8 + 24 */ } From 3485e79f07d74e47ff00b60a68d609d37d0129ba Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 15 Dec 2021 23:21:25 +0100 Subject: [PATCH 10/38] avformat/(aiff|flac|mov|mp3|tta)enc: Don't create unnecessary references The packet given to muxers is not used afterwards; it is always unreferenced by libavformat. Ergo muxers are allowed to keep the references in the packets and e.g. move the ownership to a packet list. This is what this commit does. Signed-off-by: Andreas Rheinhardt --- libavformat/aiffenc.c | 2 +- libavformat/flacenc.c | 2 +- libavformat/movenc.c | 4 +++- libavformat/mp3enc.c | 3 ++- libavformat/ttaenc.c | 3 ++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/libavformat/aiffenc.c b/libavformat/aiffenc.c index 24bc17400e..7bb0978a53 100644 --- a/libavformat/aiffenc.c +++ b/libavformat/aiffenc.c @@ -219,7 +219,7 @@ static int aiff_write_packet(AVFormatContext *s, AVPacket *pkt) return 0; return avpriv_packet_list_put(&aiff->pict_list, &aiff->pict_list_end, - pkt, av_packet_ref, 0); + pkt, NULL, 0); } return 0; diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index f884e5d2c8..e8f043729e 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -360,7 +360,7 @@ static int flac_write_packet(struct AVFormatContext *s, AVPacket *pkt) if (pkt->stream_index == c->audio_stream_idx) { if (c->waiting_pics) { /* buffer audio packets until we get all the pictures */ - ret = avpriv_packet_list_put(&c->queue, &c->queue_end, pkt, av_packet_ref, 0); + ret = avpriv_packet_list_put(&c->queue, &c->queue_end, pkt, NULL, 0); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Out of memory in packet queue; skipping attached pictures\n"); c->waiting_pics = 0; diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 04cf2f777d..e5391bb80f 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -6187,9 +6187,11 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EINVAL); } + /* The following will reset pkt and is only allowed to be used + * because we return immediately. afterwards. */ if ((ret = avpriv_packet_list_put(&trk->squashed_packet_queue, &trk->squashed_packet_queue_end, - pkt, av_packet_ref, 0)) < 0) { + pkt, NULL, 0)) < 0) { return ret; } diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index e4b2a65b07..5728ef30be 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -524,7 +524,8 @@ static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt) if (pkt->stream_index == mp3->audio_stream_idx) { if (mp3->pics_to_write) { /* buffer audio packets until we get all the pictures */ - int ret = avpriv_packet_list_put(&mp3->queue, &mp3->queue_end, pkt, av_packet_ref, 0); + int ret = avpriv_packet_list_put(&mp3->queue, &mp3->queue_end, + pkt, NULL, 0); if (ret < 0) { av_log(s, AV_LOG_WARNING, "Not enough memory to buffer audio. Skipping picture streams\n"); diff --git a/libavformat/ttaenc.c b/libavformat/ttaenc.c index 11855c32d9..5f21fdc144 100644 --- a/libavformat/ttaenc.c +++ b/libavformat/ttaenc.c @@ -95,10 +95,11 @@ static int tta_write_packet(AVFormatContext *s, AVPacket *pkt) int ret; ret = avpriv_packet_list_put(&tta->queue, &tta->queue_end, pkt, - av_packet_ref, 0); + NULL, 0); if (ret < 0) { return ret; } + pkt = &tta->queue_end->pkt; avio_wl32(tta->seek_table, pkt->size); tta->nb_samples += pkt->duration; From 20b0d24c2f7ae86cebeb17399a2fea3a7e3d0f69 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Feb 2021 12:40:04 +0100 Subject: [PATCH 11/38] Makefile: Redo duplicating object files in shared builds In case of shared builds, some object files containing tables are currently duplicated into other libraries: log2_tab.c, golomb.c, reverse.c. The check for whether this is duplicated is simply whether CONFIG_SHARED is true. Yet this is crude: E.g. libavdevice includes reverse.c for shared builds, but only needs it for the decklink input device, which given that decklink is not enabled by default will be unused in most libavdevice.so. This commit changes this by making it more explicit about what to duplicate from other libraries. To do this, two new Makefile variables were added: SHLIBOBJS and STLIBOBJS. SHLIBOBJS contains the objects that are duplicated from other libraries in case of shared builds; STLIBOBJS contains stuff that a library has to provide for other libraries in case of static builds. These new variables provide a way to enable/disable with a finer granularity than just whether shared builds are enabled or not. E.g. lavd's Makefile now contains: SHLIBOBJS-$(CONFIG_DECKLINK_INDEV) += reverse.o Another example is provided by the golomb tables. These are provided by lavc for static builds, even if one uses a build configuration that makes only lavf use them. Therefore lavc's Makefile contains STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o, whereas lavf's Makefile has a corresponding SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o. E.g. in case the MXF muxer is the only component needing these tables only libavformat.so will contain them for shared builds; currently libavcodec.so does so, too. (There is currently a CONFIG_EXTRA group for golomb. But actually one would need two groups (golomb_avcodec and golomb_avformat) in order to know when and where to include these tables. Therefore this commit uses a Makefile-based approach for this and stops using these groups for the users in libavformat.) Signed-off-by: Andreas Rheinhardt --- Makefile | 3 ++- configure | 4 ++-- ffbuild/common.mak | 10 ++++++++-- ffbuild/library.mak | 22 +++++++++++++++++++--- libavcodec/Makefile | 10 ++++++++-- libavdevice/Makefile | 4 +++- libavfilter/Makefile | 5 +++-- libavformat/Makefile | 6 +++++- libswresample/Makefile | 4 +++- libswscale/Makefile | 3 ++- 10 files changed, 55 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 5479554683..2d622ecd9c 100644 --- a/Makefile +++ b/Makefile @@ -90,7 +90,8 @@ SUBDIR_VARS := CLEANFILES FFLIBS HOSTPROGS TESTPROGS TOOLS \ ARMV5TE-OBJS ARMV6-OBJS ARMV8-OBJS VFP-OBJS NEON-OBJS \ ALTIVEC-OBJS VSX-OBJS MMX-OBJS X86ASM-OBJS \ MIPSFPU-OBJS MIPSDSPR2-OBJS MIPSDSP-OBJS MSA-OBJS \ - MMI-OBJS LSX-OBJS LASX-OBJS OBJS SLIBOBJS HOSTOBJS TESTOBJS + MMI-OBJS LSX-OBJS LASX-OBJS OBJS SLIBOBJS SHLIBOBJS \ + STLIBOBJS HOSTOBJS TESTOBJS define RESET $(1) := diff --git a/configure b/configure index e2ea473565..e16a5f34f6 100755 --- a/configure +++ b/configure @@ -3436,7 +3436,7 @@ mp4_muxer_select="mov_muxer" mpegts_demuxer_select="iso_media" mpegts_muxer_select="ac3_parser adts_muxer latm_muxer h264_mp4toannexb_bsf hevc_mp4toannexb_bsf" mpegtsraw_demuxer_select="mpegts_demuxer" -mxf_muxer_select="golomb pcm_rechunk_bsf" +mxf_muxer_select="pcm_rechunk_bsf" mxf_d10_muxer_select="mxf_muxer" mxf_opatom_muxer_select="mxf_muxer" nut_muxer_select="riffenc" @@ -3449,7 +3449,7 @@ ogv_muxer_select="ogg_muxer" opus_muxer_select="ogg_muxer" psp_muxer_select="mov_muxer" rtp_demuxer_select="sdp_demuxer" -rtp_muxer_select="golomb jpegtables" +rtp_muxer_select="jpegtables" rtp_mpegts_muxer_select="mpegts_muxer rtp_muxer" rtpdec_select="asf_demuxer jpegtables mov_demuxer mpegts_demuxer rm_demuxer rtp_protocol srtp" rtsp_demuxer_select="http_protocol rtpdec" diff --git a/ffbuild/common.mak b/ffbuild/common.mak index c13148f476..42f7b23641 100644 --- a/ffbuild/common.mak +++ b/ffbuild/common.mak @@ -157,6 +157,8 @@ include $(SRC_PATH)/ffbuild/arch.mak OBJS += $(OBJS-yes) SLIBOBJS += $(SLIBOBJS-yes) +SHLIBOBJS += $(SHLIBOBJS-yes) +STLIBOBJS += $(STLIBOBJS-yes) FFLIBS := $($(NAME)_FFLIBS) $(FFLIBS-yes) $(FFLIBS) TESTPROGS += $(TESTPROGS-yes) @@ -165,6 +167,8 @@ FFEXTRALIBS := $(LDLIBS:%=$(LD_LIB)) $(foreach lib,EXTRALIBS-$(NAME) $(FFLIBS:%= OBJS := $(sort $(OBJS:%=$(SUBDIR)%)) SLIBOBJS := $(sort $(SLIBOBJS:%=$(SUBDIR)%)) +SHLIBOBJS := $(sort $(SHLIBOBJS:%=$(SUBDIR)%)) +STLIBOBJS := $(sort $(STLIBOBJS:%=$(SUBDIR)%)) TESTOBJS := $(TESTOBJS:%=$(SUBDIR)tests/%) $(TESTPROGS:%=$(SUBDIR)tests/%.o) TESTPROGS := $(TESTPROGS:%=$(SUBDIR)tests/%$(EXESUF)) HOSTOBJS := $(HOSTPROGS:%=$(SUBDIR)%.o) @@ -200,10 +204,12 @@ $(OBJS): | $(sort $(dir $(OBJS))) $(HOBJS): | $(sort $(dir $(HOBJS))) $(HOSTOBJS): | $(sort $(dir $(HOSTOBJS))) $(SLIBOBJS): | $(sort $(dir $(SLIBOBJS))) +$(SHLIBOBJS): | $(sort $(dir $(SHLIBOBJS))) +$(STLIBOBJS): | $(sort $(dir $(STLIBOBJS))) $(TESTOBJS): | $(sort $(dir $(TESTOBJS))) $(TOOLOBJS): | tools -OUTDIRS := $(OUTDIRS) $(dir $(OBJS) $(HOBJS) $(HOSTOBJS) $(SLIBOBJS) $(TESTOBJS)) +OUTDIRS := $(OUTDIRS) $(dir $(OBJS) $(HOBJS) $(HOSTOBJS) $(SLIBOBJS) $(SHLIBOBJS) $(STLIBOBJS) $(TESTOBJS)) CLEANSUFFIXES = *.d *.gcda *.gcno *.h.c *.ho *.map *.o *.pc *.ptx *.ptx.gz *.ptx.c *.ver *.version *$(DEFAULT_X86ASMD).asm *~ *.ilk *.pdb LIBSUFFIXES = *.a *.lib *.so *.so.* *.dylib *.dll *.def *.dll.a @@ -215,4 +221,4 @@ endef $(eval $(RULES)) --include $(wildcard $(OBJS:.o=.d) $(HOSTOBJS:.o=.d) $(TESTOBJS:.o=.d) $(HOBJS:.o=.d) $(SLIBOBJS:.o=.d)) $(OBJS:.o=$(DEFAULT_X86ASMD).d) +-include $(wildcard $(OBJS:.o=.d) $(HOSTOBJS:.o=.d) $(TESTOBJS:.o=.d) $(HOBJS:.o=.d) $(SHLIBOBJS:.o=.d) $(STLIBOBJS:.o=.d) $(SLIBOBJS:.o=.d)) $(OBJS:.o=$(DEFAULT_X86ASMD).d) diff --git a/ffbuild/library.mak b/ffbuild/library.mak index 612bacb980..ad09f20da9 100644 --- a/ffbuild/library.mak +++ b/ffbuild/library.mak @@ -14,10 +14,26 @@ INSTHEADERS := $(INSTHEADERS) $(HEADERS:%=$(SUBDIR)%) all-$(CONFIG_STATIC): $(SUBDIR)$(LIBNAME) $(SUBDIR)lib$(FULLNAME).pc all-$(CONFIG_SHARED): $(SUBDIR)$(SLIBNAME) $(SUBDIR)lib$(FULLNAME).pc -LIBOBJS := $(OBJS) $(SUBDIR)%.h.o $(TESTOBJS) +LIBOBJS := $(OBJS) $(SHLIBOBJS) $(STLIBOBJS) $(SUBDIR)%.h.o $(TESTOBJS) $(LIBOBJS) $(LIBOBJS:.o=.s) $(LIBOBJS:.o=.i): CPPFLAGS += -DHAVE_AV_CONFIG_H -$(SUBDIR)$(LIBNAME): $(OBJS) +ifdef CONFIG_SHARED +# In case both shared libs and static libs are enabled, it can happen +# that a user might want to link e.g. libavformat statically, but +# libavcodec and the other libs dynamically. In this case +# libavformat won't be able to access libavcodec's internal symbols, +# so that they have to be duplicated into the archive just like +# for purely shared builds. +# Test programs are always statically linked against their library +# to be able to access their library's internals, even with shared builds. +# Yet linking against dependend libraries still uses dynamic linking. +# This means that we are in the scenario described above. +# In case only static libs are used, the linker will only use +# one of these copies; this depends on the duplicated object files +# containing exactly the same symbols. +OBJS += $(SHLIBOBJS) +endif +$(SUBDIR)$(LIBNAME): $(OBJS) $(STLIBOBJS) $(RM) $@ $(AR) $(ARFLAGS) $(AR_O) $^ $(RANLIB) $@ @@ -48,7 +64,7 @@ $(SUBDIR)lib$(NAME).ver: $(SUBDIR)lib$(NAME).v $(OBJS) $(SUBDIR)$(SLIBNAME): $(SUBDIR)$(SLIBNAME_WITH_MAJOR) $(Q)cd ./$(SUBDIR) && $(LN_S) $(SLIBNAME_WITH_MAJOR) $(SLIBNAME) -$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SLIBOBJS) $(SUBDIR)lib$(NAME).ver +$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SHLIBOBJS) $(SLIBOBJS) $(SUBDIR)lib$(NAME).ver $(SLIB_CREATE_DEF_CMD) $$(LD) $(SHFLAGS) $(LDFLAGS) $(LDSOFLAGS) $$(LD_O) $$(filter %.o,$$^) $(FFEXTRALIBS) $(SLIB_EXTRA_CMD) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 9577062eec..79c4275133 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -139,7 +139,6 @@ OBJS-$(CONFIG_QSVENC) += qsvenc.o OBJS-$(CONFIG_RANGECODER) += rangecoder.o OBJS-$(CONFIG_RDFT) += rdft.o OBJS-$(CONFIG_RV34DSP) += rv34dsp.o -OBJS-$(CONFIG_SHARED) += log2_tab.o reverse.o OBJS-$(CONFIG_SINEWIN) += sinewin.o OBJS-$(CONFIG_SNAPPY) += snappy.o OBJS-$(CONFIG_STARTCODE) += startcode.o @@ -981,7 +980,10 @@ OBJS-$(CONFIG_VP9_VDPAU_HWACCEL) += vdpau_vp9.o OBJS-$(CONFIG_VP9_VIDEOTOOLBOX_HWACCEL) += videotoolbox_vp9.o OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec.o -# libavformat dependencies +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o reverse.o + +# General libavformat dependencies OBJS-$(CONFIG_ISO_MEDIA) += mpeg4audio.o mpegaudiodata.o OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o @@ -997,6 +999,10 @@ OBJS-$(CONFIG_SPDIF_MUXER) += dca.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o +# libavformat dependencies for static builds +STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o +STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o + # libavfilter dependencies OBJS-$(CONFIG_ELBG_FILTER) += elbg.o diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 0dfe47a1f4..53efda0514 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -9,7 +9,6 @@ OBJS = alldevices.o \ utils.o \ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o -OBJS-$(CONFIG_SHARED) += reverse.o # input/output devices OBJS-$(CONFIG_ALSA_INDEV) += alsa_dec.o alsa.o timefilter.o @@ -54,6 +53,9 @@ OBJS-$(CONFIG_XV_OUTDEV) += xv.o OBJS-$(CONFIG_LIBCDIO_INDEV) += libcdio.o OBJS-$(CONFIG_LIBDC1394_INDEV) += libdc1394.o +# Objects duplicated from other libraries for shared builds +SHLIBOBJS-$(CONFIG_DECKLINK_INDEV) += reverse.o + # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += avdeviceres.o diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 090944a99c..01c0338bbb 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -577,13 +577,14 @@ OBJS-$(CONFIG_SPECTRUMSYNTH_FILTER) += vaf_spectrumsynth.o OBJS-$(CONFIG_AMOVIE_FILTER) += src_movie.o OBJS-$(CONFIG_MOVIE_FILTER) += src_movie.o +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o + # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += avfilterres.o SKIPHEADERS-$(CONFIG_LIBVIDSTAB) += vidstabutils.h -OBJS-$(CONFIG_SHARED) += log2_tab.o - SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h diff --git a/libavformat/Makefile b/libavformat/Makefile index a9afb9c042..37281d5ca8 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -61,7 +61,6 @@ OBJS-$(CONFIG_RTPDEC) += rdt.o \ rtpdec_vp9.o \ rtpdec_xiph.o OBJS-$(CONFIG_RTPENC_CHAIN) += rtpenc_chain.o rtp.o -OBJS-$(CONFIG_SHARED) += log2_tab.o golomb_tab.o OBJS-$(CONFIG_SRTP) += srtp.o # muxers/demuxers @@ -680,6 +679,11 @@ OBJS-$(CONFIG_LIBSRT_PROTOCOL) += libsrt.o OBJS-$(CONFIG_LIBSSH_PROTOCOL) += libssh.o OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o +SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o +SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o + # libavdevice dependencies OBJS-$(CONFIG_IEC61883_INDEV) += dv.o diff --git a/libswresample/Makefile b/libswresample/Makefile index 42666e4dd2..f528427f55 100644 --- a/libswresample/Makefile +++ b/libswresample/Makefile @@ -15,7 +15,9 @@ OBJS = audioconvert.o \ swresample_frame.o \ OBJS-$(CONFIG_LIBSOXR) += soxr_resample.o -OBJS-$(CONFIG_SHARED) += log2_tab.o + +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += swresampleres.o diff --git a/libswscale/Makefile b/libswscale/Makefile index 4b8f9de425..a0ec71e06f 100644 --- a/libswscale/Makefile +++ b/libswscale/Makefile @@ -19,7 +19,8 @@ OBJS = alphablend.o \ yuv2rgb.o \ vscale.o \ -OBJS-$(CONFIG_SHARED) += log2_tab.o +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += swscaleres.o From 41457e536c059d265844b1a66c906a9a842f73ab Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 16 Dec 2021 00:23:48 +0100 Subject: [PATCH 12/38] avformat/mux, mxfenc: Don't use sizeof(AVPacket) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes one of the last usages of sizeof(AVPacket) in the generic muxing code. Reviewed-by: Tomas Härdin Signed-off-by: Andreas Rheinhardt --- libavformat/mux.c | 8 +------- libavformat/mxfenc.c | 8 ++------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index d93dc73f8e..3ba95d28c6 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -1014,15 +1014,9 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, AVStream *const st = s->streams[pktl->pkt.stream_index]; FFStream *const sti = ffstream(st); - *pkt = pktl->pkt; - - si->packet_buffer = pktl->next; - if (!si->packet_buffer) - si->packet_buffer_end = NULL; - if (sti->last_in_packet_buffer == pktl) sti->last_in_packet_buffer = NULL; - av_freep(&pktl); + avpriv_packet_list_get(&si->packet_buffer, &si->packet_buffer_end, pkt); return 1; } else { diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 873d64a5fd..4c02e3e264 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -3128,14 +3128,10 @@ static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flus pktl = si->packet_buffer; } - *out = pktl->pkt; - av_log(s, AV_LOG_TRACE, "out st:%d dts:%"PRId64"\n", (*out).stream_index, (*out).dts); - si->packet_buffer = pktl->next; if (ffstream(s->streams[pktl->pkt.stream_index])->last_in_packet_buffer == pktl) ffstream(s->streams[pktl->pkt.stream_index])->last_in_packet_buffer = NULL; - if (!si->packet_buffer) - si->packet_buffer_end = NULL; - av_freep(&pktl); + avpriv_packet_list_get(&si->packet_buffer, &si->packet_buffer_end, out); + av_log(s, AV_LOG_TRACE, "out st:%d dts:%"PRId64"\n", out->stream_index, out->dts); return 1; } else { out: From 029598bd4aa696253370c4429abe3c2c95f2e788 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 16 Dec 2021 02:16:29 +0100 Subject: [PATCH 13/38] avformat/movenc: Use dedicated pointer for access to MOVTrack Improves readability and slightly decreases codesize. While just at it, also remove a check whether the packet list is nonempty before freeing it, as freeing an empty list is fine and basically a no-op. Signed-off-by: Andreas Rheinhardt --- libavformat/movenc.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index e5391bb80f..24965c89c2 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -6457,29 +6457,29 @@ static void mov_free(AVFormatContext *s) } for (i = 0; i < mov->nb_streams; i++) { - if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) - ff_mov_close_hinting(&mov->tracks[i]); - else if (mov->tracks[i].tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) - av_freep(&mov->tracks[i].par); - av_freep(&mov->tracks[i].cluster); - av_freep(&mov->tracks[i].frag_info); - av_packet_free(&mov->tracks[i].cover_image); + MOVTrack *const track = &mov->tracks[i]; - if (mov->tracks[i].eac3_priv) { - struct eac3_info *info = mov->tracks[i].eac3_priv; + if (track->tag == MKTAG('r','t','p',' ')) + ff_mov_close_hinting(track); + else if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) + av_freep(&track->par); + av_freep(&track->cluster); + av_freep(&track->frag_info); + av_packet_free(&track->cover_image); + + if (track->eac3_priv) { + struct eac3_info *info = track->eac3_priv; av_packet_free(&info->pkt); - av_freep(&mov->tracks[i].eac3_priv); + av_freep(&track->eac3_priv); } - if (mov->tracks[i].vos_len) - av_freep(&mov->tracks[i].vos_data); + if (track->vos_len) + av_freep(&track->vos_data); - ff_mov_cenc_free(&mov->tracks[i].cenc); - ffio_free_dyn_buf(&mov->tracks[i].mdat_buf); + ff_mov_cenc_free(&track->cenc); + ffio_free_dyn_buf(&track->mdat_buf); - if (mov->tracks[i].squashed_packet_queue) { - avpriv_packet_list_free(&(mov->tracks[i].squashed_packet_queue), - &(mov->tracks[i].squashed_packet_queue_end)); - } + avpriv_packet_list_free(&track->squashed_packet_queue, + &track->squashed_packet_queue_end); } av_freep(&mov->tracks); From 4c03928f4db4dab5ebed91c281e67f678cd3349d Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Sun, 2 Jan 2022 09:22:26 -0800 Subject: [PATCH 14/38] avformat/imf: Fix error handling in set_context_streams_from_tracks() Signed-off-by: Pierre-Anthony Lemieux Signed-off-by: Zane van Iperen --- libavformat/imfdec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavformat/imfdec.c b/libavformat/imfdec.c index 228ba494ae..503c8a2659 100644 --- a/libavformat/imfdec.c +++ b/libavformat/imfdec.c @@ -564,9 +564,8 @@ static int set_context_streams_from_tracks(AVFormatContext *s) /* Copy stream information */ asset_stream = avformat_new_stream(s, NULL); if (!asset_stream) { - ret = AVERROR(ENOMEM); av_log(s, AV_LOG_ERROR, "Could not create stream\n"); - break; + return AVERROR(ENOMEM); } asset_stream->id = i; ret = avcodec_parameters_copy(asset_stream->codecpar, first_resource_stream->codecpar); From 20b0b2be6c6f7c2c3949e4e004fad78748e76b9b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 4 Jan 2022 10:25:08 +0100 Subject: [PATCH 15/38] avformat/tests/imf: Don't use uninitialized value Reviewed-by: Zane van Iperen Signed-off-by: Andreas Rheinhardt --- libavformat/tests/imf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/tests/imf.c b/libavformat/tests/imf.c index 68e4c8b6af..142aa04261 100644 --- a/libavformat/tests/imf.c +++ b/libavformat/tests/imf.c @@ -347,7 +347,7 @@ static int test_bad_cpl_parsing(void) doc = xmlReadMemory(cpl_bad_doc, strlen(cpl_bad_doc), NULL, NULL, 0); if (doc == NULL) { printf("XML parsing failed.\n"); - return ret; + return 1; } ret = ff_imf_parse_cpl_from_xml_dom(doc, &cpl); From 78dc21b123e71ef49f45390d826a1c25e3805ec7 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 3 Jan 2022 09:55:11 +0100 Subject: [PATCH 16/38] lavu/frame: Add Dolby Vision metadata side data type In order to be able to extend this struct later (as the Dolby Vision RPU evolves), all of the 'container' structs are considered extensible, and the individual constituent fields must instead be accessed via offsets. The precedent for this style of access is set in Signed-off-by: Niklas Haas Signed-off-by: Andreas Rheinhardt --- doc/APIchanges | 3 + libavutil/dovi_meta.c | 25 +++++++ libavutil/dovi_meta.h | 166 ++++++++++++++++++++++++++++++++++++++++++ libavutil/frame.c | 1 + libavutil/frame.h | 9 ++- libavutil/version.h | 2 +- 6 files changed, 204 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 50b5f0bb53..0fb3f1e3d7 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,9 @@ libavutil: 2021-04-27 API changes, most recent first: +2022-01-04 - xxxxxxxxxx - lavu 57.16.100 - frame.h + Add AV_FRAME_DATA_DOVI_METADATA. + 2022-01-03 - 70f318e6b6c - lavf 59.13.100 - avformat.h Add AVFMT_EXPERIMENTAL flag. diff --git a/libavutil/dovi_meta.c b/libavutil/dovi_meta.c index 7bd08f6c54..9c50da561e 100644 --- a/libavutil/dovi_meta.c +++ b/libavutil/dovi_meta.c @@ -33,3 +33,28 @@ AVDOVIDecoderConfigurationRecord *av_dovi_alloc(size_t *size) return dovi; } + +typedef struct AVDOVIMetadataInternal { + AVDOVIMetadata metadata; + AVDOVIRpuDataHeader header; + AVDOVIDataMapping mapping; + AVDOVIColorMetadata color; +} AVDOVIMetadataInternal; + +AVDOVIMetadata *av_dovi_metadata_alloc(size_t *size) +{ + AVDOVIMetadataInternal *dovi = av_mallocz(sizeof(AVDOVIMetadataInternal)); + if (!dovi) + return NULL; + + if (size) + *size = sizeof(*dovi); + + dovi->metadata = (struct AVDOVIMetadata) { + .header_offset = offsetof(AVDOVIMetadataInternal, header), + .mapping_offset = offsetof(AVDOVIMetadataInternal, mapping), + .color_offset = offsetof(AVDOVIMetadataInternal, color), + }; + + return &dovi->metadata; +} diff --git a/libavutil/dovi_meta.h b/libavutil/dovi_meta.h index 299911d434..3d11e02bff 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,169 @@ typedef struct AVDOVIDecoderConfigurationRecord { */ AVDOVIDecoderConfigurationRecord *av_dovi_alloc(size_t *size); +/** + * Dolby Vision RPU data header. + * + * @note sizeof(AVDOVIRpuDataHeader) is not part of the public ABI. + */ +typedef struct AVDOVIRpuDataHeader { + uint8_t rpu_type; + uint16_t rpu_format; + uint8_t vdr_rpu_profile; + uint8_t vdr_rpu_level; + uint8_t 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; + uint8_t 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] */ + uint8_t spatial_resampling_filter_flag; + uint8_t el_spatial_resampling_filter_flag; + uint8_t 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 AV_DOVI_MAX_PIECES 8 +typedef struct AVDOVIReshapingCurve { + uint8_t num_pivots; /* [2, 9] */ + uint16_t pivots[AV_DOVI_MAX_PIECES + 1]; /* sorted ascending */ + enum AVDOVIMappingMethod mapping_idc[AV_DOVI_MAX_PIECES]; + /* AV_DOVI_MAPPING_POLYNOMIAL */ + uint8_t poly_order[AV_DOVI_MAX_PIECES]; /* [1, 2] */ + int64_t poly_coef[AV_DOVI_MAX_PIECES][3]; /* x^0, x^1, x^2 */ + /* AV_DOVI_MAPPING_MMR */ + uint8_t mmr_order[AV_DOVI_MAX_PIECES]; /* [1, 3] */ + int64_t mmr_constant[AV_DOVI_MAX_PIECES]; + int64_t mmr_coef[AV_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 { + uint16_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. + * + * @note sizeof(AVDOVIDataMapping) is not part of the public ABI. + */ +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; + +/** + * Dolby Vision RPU colorspace metadata parameters. + * + * @note sizeof(AVDOVIColorMetadata) is not part of the public ABI. + */ +typedef struct AVDOVIColorMetadata { + uint8_t dm_metadata_id; + uint8_t 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; + uint16_t signal_eotf_param1; + uint32_t signal_eotf_param2; + uint8_t signal_bit_depth; + uint8_t signal_color_space; + uint8_t signal_chroma_format; + uint8_t signal_full_range_flag; /* [0, 3] */ + uint16_t source_min_pq; + uint16_t source_max_pq; + uint16_t source_diagonal; +} AVDOVIColorMetadata; + +/** + * Combined struct representing a combination of header, mapping and color + * metadata, for attaching to frames as side data. + * + * @note The struct must be allocated with av_dovi_metadata_alloc() and + * its size is not a part of the public ABI. + */ + +typedef struct AVDOVIMetadata { + /** + * Offset in bytes from the beginning of this structure at which the + * respective structs start. + */ + size_t header_offset; /* AVDOVIRpuDataHeader */ + size_t mapping_offset; /* AVDOVIDataMapping */ + size_t color_offset; /* AVDOVIColorMetadata */ +} AVDOVIMetadata; + +static av_always_inline AVDOVIRpuDataHeader * +av_dovi_get_header(const AVDOVIMetadata *data) +{ + return (AVDOVIRpuDataHeader *)((uint8_t *) data + data->header_offset); +} + +static av_always_inline AVDOVIDataMapping * +av_dovi_get_mapping(const AVDOVIMetadata *data) +{ + return (AVDOVIDataMapping *)((uint8_t *) data + data->mapping_offset); +} + +static av_always_inline AVDOVIColorMetadata * +av_dovi_get_color(const AVDOVIMetadata *data) +{ + return (AVDOVIColorMetadata *)((uint8_t *) data + data->color_offset); +} + +/** + * Allocate an AVDOVIMetadata structure and initialize its + * fields to default values. + * + * @param size If this parameter is non-NULL, the size in bytes of the + * allocated struct will be written here on success + * + * @return the newly allocated struct or NULL on failure + */ +AVDOVIMetadata *av_dovi_metadata_alloc(size_t *size); + #endif /* AVUTIL_DOVI_META_H */ diff --git a/libavutil/frame.c b/libavutil/frame.c index 0912ad9131..8997c85e35 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -729,6 +729,7 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type) case AV_FRAME_DATA_FILM_GRAIN_PARAMS: return "Film grain parameters"; case AV_FRAME_DATA_DETECTION_BBOXES: return "Bounding boxes for object detection and classification"; case AV_FRAME_DATA_DOVI_RPU_BUFFER: return "Dolby Vision RPU Data"; + case AV_FRAME_DATA_DOVI_METADATA: return "Dolby Vision Metadata"; } return NULL; } diff --git a/libavutil/frame.h b/libavutil/frame.h index 3f295f6b9e..18e239f870 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -189,11 +189,18 @@ enum AVFrameSideDataType { AV_FRAME_DATA_DETECTION_BBOXES, /** - * Dolby Vision RPU data, suitable for passing to x265 + * Dolby Vision RPU raw data, suitable for passing to x265 * or other libraries. Array of uint8_t, with NAL emulation * bytes intact. */ AV_FRAME_DATA_DOVI_RPU_BUFFER, + + /** + * Parsed Dolby Vision metadata, suitable for passing to a software + * implementation. The payload is the AVDOVIMetadata struct defined in + * libavutil/dovi_meta.h. + */ + AV_FRAME_DATA_DOVI_METADATA, }; enum AVActiveFormatDescription { diff --git a/libavutil/version.h b/libavutil/version.h index ca5d34d681..d257e5438d 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 15 +#define LIBAVUTIL_VERSION_MINOR 16 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From fc40f45b9c070543dc0d7d77b299f2ae619c7acb Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 3 Jan 2022 01:27:23 +0100 Subject: [PATCH 17/38] lavfi/showinfo: Support AV_FRAME_DATA_DOVI_METADATA Signed-off-by: Niklas Haas Signed-off-by: Andreas Rheinhardt --- libavfilter/vf_showinfo.c | 108 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index 62c7833247..909ad4f8d7 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 = (AVDOVIMetadata *) sd->data; + const AVDOVIRpuDataHeader *hdr = av_dovi_get_header(dovi); + const AVDOVIDataMapping *mapping = av_dovi_get_mapping(dovi); + const AVDOVIColorMetadata *color = av_dovi_get_color(dovi); + + 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=%"PRIu8"; ", 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=%"PRIu8"; ", 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=%"PRIu8"; ", hdr->spatial_resampling_filter_flag); + av_log(ctx, AV_LOG_INFO, "el_spatial_resampling_filter_flag=%"PRIu8"; ", hdr->el_spatial_resampling_filter_flag); + av_log(ctx, AV_LOG_INFO, "disable_residual_flag=%"PRIu8"\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); + av_log(ctx, AV_LOG_INFO, "vdr_in_max=%"PRIu64"; ", nlq->vdr_in_max); + switch (mapping->nlq_method_idc) { + case AV_DOVI_NLQ_LINEAR_DZ: + av_log(ctx, AV_LOG_INFO, "linear_deadzone_slope=%"PRIu64"; ", nlq->linear_deadzone_slope); + av_log(ctx, AV_LOG_INFO, "linear_deadzone_threshold=%"PRIu64"\n", nlq->linear_deadzone_threshold); + break; + } + } + + av_log(ctx, AV_LOG_INFO, " color metadata: "); + av_log(ctx, AV_LOG_INFO, "dm_metadata_id=%"PRIu8"; ", color->dm_metadata_id); + av_log(ctx, AV_LOG_INFO, "scene_refresh_flag=%"PRIu8"; ", color->scene_refresh_flag); + av_log(ctx, AV_LOG_INFO, "ycc_to_rgb_matrix={ "); + for (int i = 0; i < 9; i++) + av_log(ctx, AV_LOG_INFO, "%f ", av_q2d(color->ycc_to_rgb_matrix[i])); + av_log(ctx, AV_LOG_INFO, "}; ycc_to_rgb_offset={ "); + for (int i = 0; i < 3; i++) + av_log(ctx, AV_LOG_INFO, "%f ", av_q2d(color->ycc_to_rgb_offset[i])); + av_log(ctx, AV_LOG_INFO, "}; rgb_to_lms_matrix={ "); + for (int i = 0; i < 9; i++) + av_log(ctx, AV_LOG_INFO, "%f ", av_q2d(color->rgb_to_lms_matrix[i])); + av_log(ctx, AV_LOG_INFO, "}; signal_eotf=%"PRIu16"; ", color->signal_eotf); + av_log(ctx, AV_LOG_INFO, "signal_eotf_param0=%"PRIu16"; ", color->signal_eotf_param0); + av_log(ctx, AV_LOG_INFO, "signal_eotf_param1=%"PRIu16"; ", color->signal_eotf_param1); + av_log(ctx, AV_LOG_INFO, "signal_eotf_param2=%"PRIu32"; ", color->signal_eotf_param2); + av_log(ctx, AV_LOG_INFO, "signal_bit_depth=%"PRIu8"; ", color->signal_bit_depth); + av_log(ctx, AV_LOG_INFO, "signal_color_space=%"PRIu8"; ", color->signal_color_space); + av_log(ctx, AV_LOG_INFO, "signal_chroma_format=%"PRIu8"; ", color->signal_chroma_format); + av_log(ctx, AV_LOG_INFO, "signal_full_range_flag=%"PRIu8"; ", color->signal_full_range_flag); + av_log(ctx, AV_LOG_INFO, "source_min_pq=%"PRIu16"; ", color->source_min_pq); + av_log(ctx, AV_LOG_INFO, "source_max_pq=%"PRIu16"; ", color->source_max_pq); + av_log(ctx, AV_LOG_INFO, "source_diagonal=%"PRIu16"; ", color->source_diagonal); +} + static void dump_color_property(AVFilterContext *ctx, AVFrame *frame) { const char *color_range_str = av_color_range_name(frame->color_range); @@ -617,6 +722,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) case AV_FRAME_DATA_FILM_GRAIN_PARAMS: dump_sei_film_grain_params_metadata(ctx, sd); break; + case AV_FRAME_DATA_DOVI_METADATA: + dump_dovi_metadata(ctx, sd); + break; default: av_log(ctx, AV_LOG_WARNING, "unknown side data type %d " "(%"SIZE_SPECIFIER" bytes)\n", sd->type, sd->size); From a3f41483194b9fc5a6d0fa258e0352236ba97d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Mon, 3 Jan 2022 01:27:24 +0100 Subject: [PATCH 18/38] ffprobe: Support AV_FRAME_DATA_DOVI_METADATA Co-authored-by: Niklas Haas Signed-off-by: Andreas Rheinhardt --- fftools/ffprobe.c | 173 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 170 insertions(+), 3 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 906bb03b16..20582ca7ac 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 } }, @@ -1809,6 +1817,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) @@ -1854,6 +1872,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 = av_dovi_get_header(dovi); + const AVDOVIDataMapping *mapping = av_dovi_get_mapping(dovi); + const AVDOVIColorMetadata *color = av_dovi_get_color(dovi); + 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", hdr->coef_log2_denom); + print_int("vdr_rpu_normalized_idc", hdr->vdr_rpu_normalized_idc); + print_int("bl_video_full_range_flag", hdr->bl_video_full_range_flag); + print_int("bl_bit_depth", hdr->bl_bit_depth); + print_int("el_bit_depth", hdr->el_bit_depth); + print_int("vdr_bit_depth", hdr->vdr_bit_depth); + print_int("spatial_resampling_filter_flag", + hdr->spatial_resampling_filter_flag); + print_int("el_spatial_resampling_filter_flag", + hdr->el_spatial_resampling_filter_flag); + print_int("disable_residual_flag", hdr->disable_residual_flag); + + // data mapping values + print_int("vdr_rpu_id", mapping->vdr_rpu_id); + print_int("mapping_color_space", mapping->mapping_color_space); + print_int("mapping_chroma_format_idc", + mapping->mapping_chroma_format_idc); + + print_int("nlq_method_idc", mapping->nlq_method_idc); + switch (mapping->nlq_method_idc) { + case AV_DOVI_NLQ_NONE: + print_str("nlq_method_idc_name", "none"); + break; + case AV_DOVI_NLQ_LINEAR_DZ: + print_str("nlq_method_idc_name", "linear_dz"); + break; + default: + print_str("nlq_method_idc_name", "unknown"); + break; + } + + print_int("num_x_partitions", mapping->num_x_partitions); + print_int("num_y_partitions", mapping->num_y_partitions); + + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST); + + for (int c = 0; c < 3; c++) { + const AVDOVIReshapingCurve *curve = &mapping->curves[c]; + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_COMPONENT); + + print_list_fmt("pivots", "%"PRIu16, curve->num_pivots, curve->pivots[idx]); + + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST); + for (int i = 0; i < curve->num_pivots - 1; i++) { + + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_PIECE); + print_int("mapping_idc", curve->mapping_idc[i]); + switch (curve->mapping_idc[i]) { + case AV_DOVI_MAPPING_POLYNOMIAL: + print_str("mapping_idc_name", "polynomial"); + print_int("poly_order", curve->poly_order[i]); + print_list_fmt("poly_coef", "%"PRIi64, + curve->poly_order[i] + 1, + curve->poly_coef[i][idx]); + break; + case AV_DOVI_MAPPING_MMR: + print_str("mapping_idc_name", "mmr"); + print_int("mmr_order", curve->mmr_order[i]); + print_int("mmr_constant", curve->mmr_constant[i]); + print_list_fmt("mmr_coef", "%"PRIi64, + curve->mmr_order[i] * 7, + curve->mmr_coef[i][0][idx]); + break; + default: + print_str("mapping_idc_name", "unknown"); + break; + } + + // SECTION_ID_FRAME_SIDE_DATA_PIECE + writer_print_section_footer(w); + } + + // SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST + writer_print_section_footer(w); + + if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) { + const AVDOVINLQParams *nlq = &mapping->nlq[c]; + print_int("nlq_offset", nlq->nlq_offset); + print_int("vdr_in_max", nlq->vdr_in_max); + + switch (mapping->nlq_method_idc) { + case AV_DOVI_NLQ_LINEAR_DZ: + print_int("linear_deadzone_slope", nlq->linear_deadzone_slope); + print_int("linear_deadzone_threshold", nlq->linear_deadzone_threshold); + break; + } + } + + // SECTION_ID_FRAME_SIDE_DATA_COMPONENT + writer_print_section_footer(w); + } + + // SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST + writer_print_section_footer(w); + + // color metadata + print_int("dm_metadata_id", color->dm_metadata_id); + print_int("scene_refresh_flag", color->scene_refresh_flag); + print_list_fmt("ycc_to_rgb_matrix", "%d/%d", + FF_ARRAY_ELEMS(color->ycc_to_rgb_matrix), + color->ycc_to_rgb_matrix[idx].num, + color->ycc_to_rgb_matrix[idx].den); + print_list_fmt("ycc_to_rgb_offset", "%d/%d", + FF_ARRAY_ELEMS(color->ycc_to_rgb_offset), + color->ycc_to_rgb_offset[idx].num, + color->ycc_to_rgb_offset[idx].den); + print_list_fmt("rgb_to_lms_matrix", "%d/%d", + FF_ARRAY_ELEMS(color->rgb_to_lms_matrix), + color->rgb_to_lms_matrix[idx].num, + color->rgb_to_lms_matrix[idx].den); + print_int("signal_eotf", color->signal_eotf); + print_int("signal_eotf_param0", color->signal_eotf_param0); + print_int("signal_eotf_param1", color->signal_eotf_param1); + print_int("signal_eotf_param2", color->signal_eotf_param2); + print_int("signal_bit_depth", color->signal_bit_depth); + print_int("signal_color_space", color->signal_color_space); + print_int("signal_chroma_format", color->signal_chroma_format); + print_int("signal_full_range_flag", color->signal_full_range_flag); + print_int("source_min_pq", color->source_min_pq); + print_int("source_max_pq", color->source_max_pq); + print_int("source_diagonal", color->source_diagonal); + + av_bprint_finalize(&pbuf, NULL); + } +} + static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *metadata) { if (!metadata) @@ -2370,6 +2535,8 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, if (tag) print_str(tag->key, tag->value); print_int("size", sd->size); + } else if (sd->type == AV_FRAME_DATA_DOVI_METADATA) { + print_dovi_metadata(w, (const AVDOVIMetadata *)sd->data); } writer_print_section_footer(w); } From fe0403373964f6a5e633eb7adf9aa104cf9d59ff Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 3 Jan 2022 01:27:25 +0100 Subject: [PATCH 19/38] lavc: Implement Dolby Vision RPU parsing 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 is similar to IEEE CRC32 but apparently different in subtle enough ways that I could not get it to pass verification no matter what parameters I fed to av_crc. It's possible the code needs some changes. - 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 Signed-off-by: Andreas Rheinhardt --- configure | 2 + libavcodec/Makefile | 1 + libavcodec/dovi_rpu.c | 449 ++++++++++++++++++++++++++++++++++++++++++ libavcodec/dovi_rpu.h | 87 ++++++++ 4 files changed, 539 insertions(+) create mode 100644 libavcodec/dovi_rpu.c create mode 100644 libavcodec/dovi_rpu.h diff --git a/configure b/configure index e16a5f34f6..34878117e7 100755 --- a/configure +++ b/configure @@ -2434,6 +2434,7 @@ CONFIG_EXTRA=" cbs_vp9 dirac_parse dnn + dovi_rpu dvprofile exif faandct @@ -2706,6 +2707,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 79c4275133..e048a1c377 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 0000000000..a87562c8a3 --- /dev/null +++ b/libavcodec/dovi_rpu.c @@ -0,0 +1,449 @@ +/* + * 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 < FF_ARRAY_ELEMS(s->vdr_ref); i++) + av_buffer_unref(&s->vdr_ref[i]); + + *s = (DOVIContext) { + .logctx = s->logctx, + }; +} + +void ff_dovi_ctx_flush(DOVIContext *s) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(s->vdr_ref); i++) + av_buffer_unref(&s->vdr_ref[i]); + + *s = (DOVIContext) { + .logctx = s->logctx, + .dv_profile = s->dv_profile, + }; +} + +int ff_dovi_ctx_replace(DOVIContext *s, const DOVIContext *s0) +{ + int ret; + s->logctx = s0->logctx; + s->mapping = s0->mapping; + s->color = s0->color; + s->dv_profile = s0->dv_profile; + for (int i = 0; i < DOVI_MAX_DM_ID; i++) { + if ((ret = av_buffer_replace(&s->vdr_ref[i], s0->vdr_ref[i])) < 0) + goto fail; + } + + return 0; + +fail: + ff_dovi_ctx_unref(s); + return ret; +} + +void ff_dovi_update_cfg(DOVIContext *s, const AVDOVIDecoderConfigurationRecord *cfg) +{ + if (!cfg) + return; + + s->dv_profile = cfg->dv_profile; +} + +int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame) +{ + AVFrameSideData *sd; + AVBufferRef *buf; + AVDOVIMetadata *dovi; + size_t dovi_size; + + if (!s->mapping || !s->color) + return 0; /* incomplete dovi metadata */ + + dovi = av_dovi_metadata_alloc(&dovi_size); + if (!dovi) + return AVERROR(ENOMEM); + + buf = av_buffer_create((uint8_t *) dovi, dovi_size, NULL, NULL, 0); + if (!buf) { + av_free(dovi); + return AVERROR(ENOMEM); + } + + sd = av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_DOVI_METADATA, buf); + if (!sd) { + av_buffer_unref(&buf); + return AVERROR(ENOMEM); + } + + /* Copy only the parts of these structs known to us at compiler-time. */ +#define COPY(t, a, b, last) memcpy(a, b, offsetof(t, last) + sizeof((b)->last)) + COPY(AVDOVIRpuDataHeader, av_dovi_get_header(dovi), &s->header, disable_residual_flag); + COPY(AVDOVIDataMapping, av_dovi_get_mapping(dovi), s->mapping, nlq[2].linear_deadzone_threshold); + COPY(AVDOVIColorMetadata, av_dovi_get_color(dovi), s->color, source_diagonal); + return 0; +} + +static int guess_profile(const AVDOVIRpuDataHeader *hdr) +{ + switch (hdr->vdr_rpu_profile) { + case 0: + if (hdr->bl_video_full_range_flag) + return 5; + break; + case 1: + if (hdr->el_spatial_resampling_filter_flag && !hdr->disable_residual_flag) { + if (hdr->vdr_bit_depth == 12) { + return 7; + } else { + return 4; + } + } else { + return 8; + } + } + + return 0; /* unknown */ +} + +static inline uint64_t get_ue_coef(GetBitContext *gb, const AVDOVIRpuDataHeader *hdr) +{ + uint64_t ipart; + union { uint32_t u32; float f32; } fpart; + + switch (hdr->coef_data_type) { + case RPU_COEFF_FIXED: + ipart = get_ue_golomb_long(gb); + fpart.u32 = get_bits_long(gb, hdr->coef_log2_denom); + return (ipart << hdr->coef_log2_denom) + fpart.u32; + + case RPU_COEFF_FLOAT: + fpart.u32 = get_bits_long(gb, 32); + return fpart.f32 * (1 << hdr->coef_log2_denom); + } + + return 0; /* unreachable */ +} + +static inline int64_t get_se_coef(GetBitContext *gb, const AVDOVIRpuDataHeader *hdr) +{ + int64_t ipart; + union { uint32_t u32; float f32; } fpart; + + switch (hdr->coef_data_type) { + case RPU_COEFF_FIXED: + ipart = get_se_golomb_long(gb); + fpart.u32 = get_bits_long(gb, hdr->coef_log2_denom); + return (ipart << hdr->coef_log2_denom) + fpart.u32; + + case RPU_COEFF_FLOAT: + fpart.u32 = get_bits_long(gb, 32); + return fpart.f32 * (1 << hdr->coef_log2_denom); + } + + return 0; /* unreachable */ +} + +#define VALIDATE(VAR, MIN, MAX) \ + do { \ + if (VAR < MIN || VAR > MAX) { \ + av_log(s->logctx, AV_LOG_ERROR, "RPU validation failed: " \ + #MIN" <= "#VAR" = %d <= "#MAX"\n", (int) VAR); \ + goto fail; \ + } \ + } while (0) + +int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size) +{ + AVDOVIRpuDataHeader *hdr = &s->header; + GetBitContext *gb = &(GetBitContext){0}; + DOVIVdrRef *vdr; + int ret; + + uint8_t nal_prefix; + uint8_t rpu_type; + uint8_t vdr_seq_info_present; + uint8_t vdr_dm_metadata_present; + uint8_t use_prev_vdr_rpu; + uint8_t use_nlq; + uint8_t profile; + if ((ret = init_get_bits8(gb, rpu, rpu_size)) < 0) + return ret; + + /* RPU header, common values */ + nal_prefix = get_bits(gb, 8); + VALIDATE(nal_prefix, 25, 25); + rpu_type = get_bits(gb, 6); + if (rpu_type != 2) { + av_log(s->logctx, AV_LOG_WARNING, "Unrecognized RPU type " + "%"PRIu8", ignoring\n", rpu_type); + return 0; + } + + hdr->rpu_type = rpu_type; + hdr->rpu_format = get_bits(gb, 11); + + /* Values specific to RPU type 2 */ + hdr->vdr_rpu_profile = get_bits(gb, 4); + hdr->vdr_rpu_level = get_bits(gb, 4); + + vdr_seq_info_present = get_bits1(gb); + if (vdr_seq_info_present) { + hdr->chroma_resampling_explicit_filter_flag = get_bits1(gb); + hdr->coef_data_type = get_bits(gb, 2); + VALIDATE(hdr->coef_data_type, RPU_COEFF_FIXED, RPU_COEFF_FLOAT); + switch (hdr->coef_data_type) { + case RPU_COEFF_FIXED: + hdr->coef_log2_denom = get_ue_golomb(gb); + VALIDATE(hdr->coef_log2_denom, 13, 32); + break; + case RPU_COEFF_FLOAT: + hdr->coef_log2_denom = 32; /* arbitrary, choose maximum precision */ + break; + } + + hdr->vdr_rpu_normalized_idc = get_bits(gb, 2); + hdr->bl_video_full_range_flag = get_bits1(gb); + + if ((hdr->rpu_format & 0x700) == 0) { + int bl_bit_depth_minus8 = get_ue_golomb_31(gb); + int el_bit_depth_minus8 = get_ue_golomb_31(gb); + int vdr_bit_depth_minus8 = get_ue_golomb_31(gb); + VALIDATE(bl_bit_depth_minus8, 0, 8); + VALIDATE(el_bit_depth_minus8, 0, 8); + VALIDATE(vdr_bit_depth_minus8, 0, 8); + hdr->bl_bit_depth = bl_bit_depth_minus8 + 8; + hdr->el_bit_depth = el_bit_depth_minus8 + 8; + hdr->vdr_bit_depth = vdr_bit_depth_minus8 + 8; + hdr->spatial_resampling_filter_flag = get_bits1(gb); + skip_bits(gb, 3); /* reserved_zero_3bits */ + hdr->el_spatial_resampling_filter_flag = get_bits1(gb); + hdr->disable_residual_flag = get_bits1(gb); + } + } + + if (!hdr->bl_bit_depth) { + av_log(s->logctx, AV_LOG_ERROR, "Missing RPU VDR sequence info?\n"); + goto fail; + } + + vdr_dm_metadata_present = get_bits1(gb); + use_prev_vdr_rpu = get_bits1(gb); + use_nlq = (hdr->rpu_format & 0x700) == 0 && !hdr->disable_residual_flag; + + profile = s->dv_profile ? s->dv_profile : guess_profile(hdr); + if (profile == 5 && use_nlq) { + av_log(s->logctx, AV_LOG_ERROR, "Profile 5 RPUs should not use NLQ\n"); + goto fail; + } + + if (use_prev_vdr_rpu) { + int prev_vdr_rpu_id = get_ue_golomb_31(gb); + VALIDATE(prev_vdr_rpu_id, 0, DOVI_MAX_DM_ID); + if (!s->vdr_ref[prev_vdr_rpu_id]) { + av_log(s->logctx, AV_LOG_ERROR, "Unknown previous RPU ID: %u\n", + prev_vdr_rpu_id); + goto fail; + } + vdr = (DOVIVdrRef *) s->vdr_ref[prev_vdr_rpu_id]->data; + s->mapping = &vdr->mapping; + } else { + int vdr_rpu_id = get_ue_golomb_31(gb); + VALIDATE(vdr_rpu_id, 0, DOVI_MAX_DM_ID); + if (!s->vdr_ref[vdr_rpu_id]) { + s->vdr_ref[vdr_rpu_id] = av_buffer_allocz(sizeof(DOVIVdrRef)); + if (!s->vdr_ref[vdr_rpu_id]) + return AVERROR(ENOMEM); + } + + vdr = (DOVIVdrRef *) s->vdr_ref[vdr_rpu_id]->data; + s->mapping = &vdr->mapping; + + vdr->mapping.vdr_rpu_id = vdr_rpu_id; + vdr->mapping.mapping_color_space = get_ue_golomb_31(gb); + vdr->mapping.mapping_chroma_format_idc = get_ue_golomb_31(gb); + + for (int c = 0; c < 3; c++) { + AVDOVIReshapingCurve *curve = &vdr->mapping.curves[c]; + int num_pivots_minus_2 = get_ue_golomb_31(gb); + int pivot = 0; + + VALIDATE(num_pivots_minus_2, 0, AV_DOVI_MAX_PIECES - 1); + curve->num_pivots = num_pivots_minus_2 + 2; + for (int i = 0; i < curve->num_pivots; i++) { + pivot += get_bits(gb, hdr->bl_bit_depth); + curve->pivots[i] = av_clip_uint16(pivot); + } + } + + if (use_nlq) { + vdr->mapping.nlq_method_idc = get_bits(gb, 3); + /** + * The patent mentions another legal value, NLQ_MU_LAW, but it's + * not documented anywhere how to parse or apply that type of NLQ. + */ + VALIDATE(vdr->mapping.nlq_method_idc, 0, AV_DOVI_NLQ_LINEAR_DZ); + } else { + vdr->mapping.nlq_method_idc = AV_DOVI_NLQ_NONE; + } + + vdr->mapping.num_x_partitions = get_ue_golomb_long(gb) + 1; + vdr->mapping.num_y_partitions = get_ue_golomb_long(gb) + 1; + /* End of rpu_data_header(), start of vdr_rpu_data_payload() */ + + for (int c = 0; c < 3; c++) { + AVDOVIReshapingCurve *curve = &vdr->mapping.curves[c]; + for (int i = 0; i < curve->num_pivots - 1; i++) { + int mapping_idc = get_ue_golomb_31(gb); + VALIDATE(mapping_idc, 0, 1); + curve->mapping_idc[i] = mapping_idc; + switch (mapping_idc) { + case AV_DOVI_MAPPING_POLYNOMIAL: { + int poly_order_minus1 = get_ue_golomb_31(gb); + VALIDATE(poly_order_minus1, 0, 1); + curve->poly_order[i] = poly_order_minus1 + 1; + if (poly_order_minus1 == 0) { + int linear_interp_flag = get_bits1(gb); + if (linear_interp_flag) { + /* lack of documentation/samples */ + avpriv_request_sample(s->logctx, "Dolby Vision " + "linear interpolation"); + ff_dovi_ctx_unref(s); + return AVERROR_PATCHWELCOME; + } + } + for (int k = 0; k <= curve->poly_order[i]; k++) + curve->poly_coef[i][k] = get_se_coef(gb, hdr); + break; + } + case AV_DOVI_MAPPING_MMR: { + int mmr_order_minus1 = get_bits(gb, 2); + VALIDATE(mmr_order_minus1, 0, 2); + curve->mmr_order[i] = mmr_order_minus1 + 1; + curve->mmr_constant[i] = get_se_coef(gb, hdr); + for (int j = 0; j < curve->mmr_order[i]; j++) { + for (int k = 0; k < 7; k++) + curve->mmr_coef[i][j][k] = get_se_coef(gb, hdr); + } + break; + } + } + } + } + + if (use_nlq) { + for (int c = 0; c < 3; c++) { + AVDOVINLQParams *nlq = &vdr->mapping.nlq[c]; + nlq->nlq_offset = get_bits(gb, hdr->el_bit_depth); + nlq->vdr_in_max = get_ue_coef(gb, hdr); + switch (vdr->mapping.nlq_method_idc) { + case AV_DOVI_NLQ_LINEAR_DZ: + nlq->linear_deadzone_slope = get_ue_coef(gb, hdr); + nlq->linear_deadzone_threshold = get_ue_coef(gb, hdr); + break; + } + } + } + } + + if (vdr_dm_metadata_present) { + AVDOVIColorMetadata *color; + int affected_dm_id = get_ue_golomb_31(gb); + int current_dm_id = get_ue_golomb_31(gb); + VALIDATE(affected_dm_id, 0, DOVI_MAX_DM_ID); + VALIDATE(current_dm_id, 0, DOVI_MAX_DM_ID); + if (!s->vdr_ref[affected_dm_id]) { + s->vdr_ref[affected_dm_id] = av_buffer_allocz(sizeof(DOVIVdrRef)); + if (!s->vdr_ref[affected_dm_id]) + return AVERROR(ENOMEM); + } + + if (!s->vdr_ref[current_dm_id]) { + av_log(s->logctx, AV_LOG_ERROR, "Unknown previous RPU DM ID: %u\n", + current_dm_id); + goto fail; + } + + /* Update current pointer based on current_dm_id */ + vdr = (DOVIVdrRef *) s->vdr_ref[current_dm_id]->data; + s->color = &vdr->color; + + /* Update values of affected_dm_id */ + vdr = (DOVIVdrRef *) s->vdr_ref[affected_dm_id]->data; + color = &vdr->color; + color->dm_metadata_id = affected_dm_id; + color->scene_refresh_flag = get_ue_golomb_31(gb); + for (int i = 0; i < 9; i++) + color->ycc_to_rgb_matrix[i] = av_make_q(get_sbits(gb, 16), 1 << 13); + for (int i = 0; i < 3; i++) { + int denom = profile == 4 ? (1 << 30) : (1 << 28); + unsigned offset = get_bits_long(gb, 32); + if (offset > INT_MAX) { + /* Ensure the result fits inside AVRational */ + offset >>= 1; + denom >>= 1; + } + color->ycc_to_rgb_offset[i] = av_make_q(offset, denom); + } + for (int i = 0; i < 9; i++) + color->rgb_to_lms_matrix[i] = av_make_q(get_sbits(gb, 16), 1 << 14); + + color->signal_eotf = get_bits(gb, 16); + color->signal_eotf_param0 = get_bits(gb, 16); + color->signal_eotf_param1 = get_bits(gb, 16); + color->signal_eotf_param2 = get_bits_long(gb, 32); + color->signal_bit_depth = get_bits(gb, 5); + VALIDATE(color->signal_bit_depth, 8, 16); + color->signal_color_space = get_bits(gb, 2); + color->signal_chroma_format = get_bits(gb, 2); + color->signal_full_range_flag = get_bits(gb, 2); + color->source_min_pq = get_bits(gb, 12); + color->source_max_pq = get_bits(gb, 12); + color->source_diagonal = get_bits(gb, 10); + } + + /* FIXME: verify CRC32, requires implementation of AV_CRC_32_MPEG_2 */ + return 0; + +fail: + ff_dovi_ctx_unref(s); /* don't leak potentially invalid state */ + return AVERROR(EINVAL); +} diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h new file mode 100644 index 0000000000..f6ca5bbbc5 --- /dev/null +++ b/libavcodec/dovi_rpu.h @@ -0,0 +1,87 @@ +/* + * 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 + */ + +#ifndef AVCODEC_DOVI_RPU_H +#define AVCODEC_DOVI_RPU_H + +#include "libavutil/dovi_meta.h" +#include "libavutil/frame.h" + +#define DOVI_MAX_DM_ID 15 +typedef struct DOVIContext { + void *logctx; + + /** + * Currently active RPU data header, updates on every dovi_rpu_parse(). + */ + AVDOVIRpuDataHeader header; + + /** + * Currently active data mappings, or NULL. Points into memory owned by the + * corresponding rpu/vdr_ref, which becomes invalid on the next call to + * dovi_rpu_parse. + */ + const AVDOVIDataMapping *mapping; + const AVDOVIColorMetadata *color; + + /** + * Private fields internal to dovi_rpu.c + */ + AVBufferRef *vdr_ref[DOVI_MAX_DM_ID+1]; + uint8_t dv_profile; + +} DOVIContext; + +int ff_dovi_ctx_replace(DOVIContext *s, const DOVIContext *s0); + +/** + * Completely reset a DOVIContext, preserving only logctx. + */ +void ff_dovi_ctx_unref(DOVIContext *s); + +/** + * Partially reset the internal state. Resets per-frame state while preserving + * fields parsed from the configuration record. + */ +void ff_dovi_ctx_flush(DOVIContext *s); + +/** + * Read the contents of an AVDOVIDecoderConfigurationRecord (usually provided + * by stream side data) and update internal state accordingly. + */ +void ff_dovi_update_cfg(DOVIContext *s, const AVDOVIDecoderConfigurationRecord *cfg); + +/** + * Parse the contents of a Dovi RPU NAL and update the parsed values in the + * DOVIContext struct. + * + * Returns 0 or an error code. + */ +int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size); + +/** + * Attach the decoded AVDOVIMetadata as side data to an AVFrame. + */ +int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame); + +#endif /* AVCODEC_DOVI_RPU_H */ From 08d151884b8290cb7d31000565c257ae886ba375 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 3 Jan 2022 01:27:26 +0100 Subject: [PATCH 20/38] fate: Limit Dolby Vision RPU test frame count 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 Signed-off-by: Andreas Rheinhardt --- 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 6528df6e27..f294cff414 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] -[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] -[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] From a538df7eab19ecd0e2d59ef13a84e343de7f65b7 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Mon, 3 Jan 2022 01:27:27 +0100 Subject: [PATCH 21/38] lavc/hevcdec: Parse DOVI RPU NALs 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 Signed-off-by: Andreas Rheinhardt --- configure | 2 +- libavcodec/hevcdec.c | 37 ++++-- libavcodec/hevcdec.h | 2 + tests/ref/fate/hevc-dv-rpu | 224 +++++++++++++++++++++++++++++++++++++ 4 files changed, 256 insertions(+), 9 deletions(-) diff --git a/configure b/configure index 34878117e7..50aa0d596d 100755 --- a/configure +++ b/configure @@ -2826,7 +2826,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 3aa70e2245..8d7a4f7147 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 && @@ -2977,6 +2978,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; } @@ -3308,16 +3312,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 */ @@ -3450,8 +3461,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) { @@ -3463,14 +3474,17 @@ 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) + ff_dovi_update_cfg(&s->dovi_ctx, (AVDOVIDecoderConfigurationRecord *) sd); + s->ref = NULL; ret = decode_nal_units(s, avpkt->data, avpkt->size); if (ret < 0) @@ -3563,6 +3577,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) pic_arrays_free(s); + ff_dovi_ctx_unref(&s->dovi_ctx); av_buffer_unref(&s->rpu_buf); av_freep(&s->md5_ctx); @@ -3647,6 +3662,7 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ff_bswapdsp_init(&s->bdsp); + s->dovi_ctx.logctx = avctx; s->context_initialized = 1; s->eos = 0; @@ -3755,6 +3771,10 @@ static int hevc_update_thread_context(AVCodecContext *dst, if (ret < 0) return ret; + ret = ff_dovi_ctx_replace(&s->dovi_ctx, &s0->dovi_ctx); + if (ret < 0) + return ret; + s->sei.frame_packing = s0->sei.frame_packing; s->sei.display_orientation = s0->sei.display_orientation; s->sei.mastering_display = s0->sei.mastering_display; @@ -3811,6 +3831,7 @@ static void hevc_decode_flush(AVCodecContext *avctx) HEVCContext *s = avctx->priv_data; ff_hevc_flush_dpb(s); ff_hevc_reset_sei(&s->sei); + ff_dovi_ctx_flush(&s->dovi_ctx); av_buffer_unref(&s->rpu_buf); s->max_ra = INT_MAX; s->eos = 1; diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 870ff178d4..157bc6926f 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -32,6 +32,7 @@ #include "avcodec.h" #include "bswapdsp.h" #include "cabac.h" +#include "dovi_rpu.h" #include "get_bits.h" #include "hevcpred.h" #include "h2645_parse.h" @@ -574,6 +575,7 @@ typedef struct HEVCContext { int nuh_layer_id; AVBufferRef *rpu_buf; ///< 0 or 1 Dolby Vision RPUs. + DOVIContext dovi_ctx; ///< Dolby Vision decoding context } HEVCContext; /** diff --git a/tests/ref/fate/hevc-dv-rpu b/tests/ref/fate/hevc-dv-rpu index 416d9c51a6..1980ab13ea 100644 --- a/tests/ref/fate/hevc-dv-rpu +++ b/tests/ref/fate/hevc-dv-rpu @@ -5,9 +5,233 @@ side_data_type=H.26[45] User Data Unregistered SEI message [SIDE_DATA] side_data_type=Dolby Vision RPU Data [/SIDE_DATA] +[SIDE_DATA] +side_data_type=Dolby Vision Metadata +rpu_type=2 +rpu_format=18 +vdr_rpu_profile=1 +vdr_rpu_level=0 +chroma_resampling_explicit_filter_flag=0 +coef_data_type=0 +coef_log2_denom=23 +vdr_rpu_normalized_idc=1 +bl_video_full_range_flag=0 +bl_bit_depth=10 +el_bit_depth=10 +vdr_bit_depth=12 +spatial_resampling_filter_flag=0 +el_spatial_resampling_filter_flag=0 +disable_residual_flag=1 +vdr_rpu_id=0 +mapping_color_space=0 +mapping_chroma_format_idc=0 +nlq_method_idc=-1 +nlq_method_idc_name=none +num_x_partitions=1 +num_y_partitions=1 +[COMPONENT] +pivots=63 132 362 618 874 911 927 935 942 +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=-409680 16721463 -20276640 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=-119056 13575212 -12867889 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=1317527 5338528 -948122 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=2119979 2065496 2288524 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=7982780 -11367226 9973944 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=53792084 -114243184 67724328 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=112973872 -244837568 139764480 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=236828416 -518849056 291306944 +[/SECTION] +[/COMPONENT] +[COMPONENT] +pivots=0 1023 +[SECTION] +mapping_idc=1 +mapping_idc_name=mmr +mmr_order=3 +mmr_constant=-4200453 +mmr_coef=9094176 31944476 739652 -27103344 -3431599 -11015088 22758042 -2028643 -30021218 -906885 26272992 7291404 16488745 -78087176 -1487777 12496543 762460 -4281948 -5768035 -7843163 103636960 +[/SECTION] +[/COMPONENT] +[COMPONENT] +pivots=0 1023 +[SECTION] +mapping_idc=1 +mapping_idc_name=mmr +mmr_order=3 +mmr_constant=-10387889 +mmr_coef=29604202 3214133 46206184 -8564340 -53383996 1628407 5426045 -21634202 -5251953 -50812292 19221972 76726656 -425892 -35041240 5917361 2863974 25030554 -14404292 -41230120 1229046 53575140 +[/SECTION] +[/COMPONENT] +dm_metadata_id=0 +scene_refresh_flag=1 +ycc_to_rgb_matrix=9574/8192 0/8192 13802/8192 9574/8192 -1540/8192 -5348/8192 9574/8192 17610/8192 0/8192 +ycc_to_rgb_offset=16777216/268435456 134217728/268435456 134217728/268435456 +rgb_to_lms_matrix=7222/16384 8771/16384 390/16384 2654/16384 12430/16384 1300/16384 0/16384 422/16384 15962/16384 +signal_eotf=65535 +signal_eotf_param0=0 +signal_eotf_param1=0 +signal_eotf_param2=0 +signal_bit_depth=12 +signal_color_space=0 +signal_chroma_format=0 +signal_full_range_flag=1 +source_min_pq=0 +source_max_pq=3079 +source_diagonal=42 +[/SIDE_DATA] [/FRAME] [FRAME] [SIDE_DATA] side_data_type=Dolby Vision RPU Data [/SIDE_DATA] +[SIDE_DATA] +side_data_type=Dolby Vision Metadata +rpu_type=2 +rpu_format=18 +vdr_rpu_profile=1 +vdr_rpu_level=0 +chroma_resampling_explicit_filter_flag=0 +coef_data_type=0 +coef_log2_denom=23 +vdr_rpu_normalized_idc=1 +bl_video_full_range_flag=0 +bl_bit_depth=10 +el_bit_depth=10 +vdr_bit_depth=12 +spatial_resampling_filter_flag=0 +el_spatial_resampling_filter_flag=0 +disable_residual_flag=1 +vdr_rpu_id=0 +mapping_color_space=0 +mapping_chroma_format_idc=0 +nlq_method_idc=-1 +nlq_method_idc_name=none +num_x_partitions=1 +num_y_partitions=1 +[COMPONENT] +pivots=63 132 362 618 874 911 927 935 942 +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=-409680 16721463 -20276640 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=-119056 13575212 -12867889 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=1317527 5338528 -948122 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=2119979 2065496 2288524 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=7982780 -11367226 9973944 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=53792084 -114243184 67724328 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=112973872 -244837568 139764480 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=236828416 -518849056 291306944 +[/SECTION] +[/COMPONENT] +[COMPONENT] +pivots=0 1023 +[SECTION] +mapping_idc=1 +mapping_idc_name=mmr +mmr_order=3 +mmr_constant=-4200453 +mmr_coef=9094176 31944476 739652 -27103344 -3431599 -11015088 22758042 -2028643 -30021218 -906885 26272992 7291404 16488745 -78087176 -1487777 12496543 762460 -4281948 -5768035 -7843163 103636960 +[/SECTION] +[/COMPONENT] +[COMPONENT] +pivots=0 1023 +[SECTION] +mapping_idc=1 +mapping_idc_name=mmr +mmr_order=3 +mmr_constant=-10387889 +mmr_coef=29604202 3214133 46206184 -8564340 -53383996 1628407 5426045 -21634202 -5251953 -50812292 19221972 76726656 -425892 -35041240 5917361 2863974 25030554 -14404292 -41230120 1229046 53575140 +[/SECTION] +[/COMPONENT] +dm_metadata_id=0 +scene_refresh_flag=1 +ycc_to_rgb_matrix=9574/8192 0/8192 13802/8192 9574/8192 -1540/8192 -5348/8192 9574/8192 17610/8192 0/8192 +ycc_to_rgb_offset=16777216/268435456 134217728/268435456 134217728/268435456 +rgb_to_lms_matrix=7222/16384 8771/16384 390/16384 2654/16384 12430/16384 1300/16384 0/16384 422/16384 15962/16384 +signal_eotf=65535 +signal_eotf_param0=0 +signal_eotf_param1=0 +signal_eotf_param2=0 +signal_bit_depth=12 +signal_color_space=0 +signal_chroma_format=0 +signal_full_range_flag=1 +source_min_pq=0 +source_max_pq=3079 +source_diagonal=42 +[/SIDE_DATA] [/FRAME] From 9c91930ef799b855bda9fb578fff5949f3bf2525 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 4 Jan 2022 12:40:07 +0100 Subject: [PATCH 22/38] doc/APIchanges: Fill in the commit hash for DOVI metadata addition Signed-off-by: Andreas Rheinhardt --- doc/APIchanges | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 0fb3f1e3d7..8df0364e4c 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,7 +14,7 @@ libavutil: 2021-04-27 API changes, most recent first: -2022-01-04 - xxxxxxxxxx - lavu 57.16.100 - frame.h +2022-01-04 - 78dc21b123e - lavu 57.16.100 - frame.h Add AV_FRAME_DATA_DOVI_METADATA. 2022-01-03 - 70f318e6b6c - lavf 59.13.100 - avformat.h From d1f7700133312929d64aaa69ab3a08b5ae171390 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Sun, 2 Jan 2022 10:49:36 +0100 Subject: [PATCH 23/38] avdevice/dshow: tv_tuner_audio_dialog cleanup missing Cleanup was missing for when the show_analog_tv_tuner_audio_dialog is true. Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow_crossbar.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavdevice/dshow_crossbar.c b/libavdevice/dshow_crossbar.c index 2438683cde..961defe690 100644 --- a/libavdevice/dshow_crossbar.c +++ b/libavdevice/dshow_crossbar.c @@ -204,5 +204,9 @@ end: IAMTVTuner_Release(tv_tuner_filter); if (tv_tuner_base_filter) IBaseFilter_Release(tv_tuner_base_filter); + if (tv_audio_filter) + IAMAudioInputMixer_Release(tv_audio_filter); + if (tv_audio_base_filter) + IBaseFilter_Release(tv_audio_base_filter); return hr; } From 307d2b867f35cb18f9ff6085f7e5298c3f0be278 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Sun, 2 Jan 2022 10:49:37 +0100 Subject: [PATCH 24/38] avdevice/dshow: proper cleanup of queried media types Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 30f1be1ead..4b6887881d 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -953,7 +953,7 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, av_log(avctx, AV_LOG_INFO, "(%s)", chroma ? chroma : "unknown"); av_log(avctx, AV_LOG_INFO, "\n"); - continue; + goto next; } if (requested_video_codec_id != AV_CODEC_ID_RAWVIDEO) { if (requested_video_codec_id != fmt_info->codec_id) @@ -1038,6 +1038,7 @@ next: if (type && type->pbFormat) CoTaskMemFree(type->pbFormat); CoTaskMemFree(type); + type = NULL; } // previously found a matching VIDEOINFOHEADER format and stored // it for safe keeping. Searching further for a matching From 76e164f3326c3c2330f3fdd22716ca2495e7c612 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Sun, 2 Jan 2022 10:49:38 +0100 Subject: [PATCH 25/38] avdevice/dshow: fix crash on x86 fix regression introduced in 911ba8417e8881a7380842e69e11ca05fdc46575. Removal of WINAPI decoration from function signatures caused crashed when using dshow on x86. Fixes #9568 Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow_capture.h | 118 ++++++++++++++--------------- libavdevice/dshow_enummediatypes.c | 8 +- libavdevice/dshow_enumpins.c | 8 +- libavdevice/dshow_filter.c | 24 +++--- libavdevice/dshow_pin.c | 48 ++++++------ 5 files changed, 103 insertions(+), 103 deletions(-) diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index 5a2691518c..21f5cf7e83 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -70,7 +70,7 @@ enum dshowSourceFilterType { }; #define DECLARE_QUERYINTERFACE(prefix, class, ...) \ -long \ +long WINAPI \ ff_dshow_##prefix##_QueryInterface(class *this, const GUID *riid, void **ppvObject) \ { \ struct GUIDoffset ifaces[] = __VA_ARGS__; \ @@ -93,14 +93,14 @@ ff_dshow_##prefix##_QueryInterface(class *this, const GUID *riid, void **ppvObje return E_NOINTERFACE; \ } #define DECLARE_ADDREF(prefix, class) \ -unsigned long \ +unsigned long WINAPI \ ff_dshow_##prefix##_AddRef(class *this) \ { \ dshowdebug("ff_dshow_"AV_STRINGIFY(prefix)"_AddRef(%p)\t%ld\n", this, this->ref+1); \ return InterlockedIncrement(&this->ref); \ } #define DECLARE_RELEASE(prefix, class) \ -unsigned long \ +unsigned long WINAPI \ ff_dshow_##prefix##_Release(class *this) \ { \ long ref = InterlockedDecrement(&this->ref); \ @@ -167,34 +167,34 @@ struct DShowPin { IMemInputPinVtbl *imemvtbl; }; -long ff_dshow_pin_QueryInterface (DShowPin *, const GUID *, void **); -unsigned long ff_dshow_pin_AddRef (DShowPin *); -unsigned long ff_dshow_pin_Release (DShowPin *); -long ff_dshow_pin_Connect (DShowPin *, IPin *, const AM_MEDIA_TYPE *); -long ff_dshow_pin_ReceiveConnection (DShowPin *, IPin *, const AM_MEDIA_TYPE *); -long ff_dshow_pin_Disconnect (DShowPin *); -long ff_dshow_pin_ConnectedTo (DShowPin *, IPin **); -long ff_dshow_pin_ConnectionMediaType (DShowPin *, AM_MEDIA_TYPE *); -long ff_dshow_pin_QueryPinInfo (DShowPin *, PIN_INFO *); -long ff_dshow_pin_QueryDirection (DShowPin *, PIN_DIRECTION *); -long ff_dshow_pin_QueryId (DShowPin *, wchar_t **); -long ff_dshow_pin_QueryAccept (DShowPin *, const AM_MEDIA_TYPE *); -long ff_dshow_pin_EnumMediaTypes (DShowPin *, IEnumMediaTypes **); -long ff_dshow_pin_QueryInternalConnections(DShowPin *, IPin **, unsigned long *); -long ff_dshow_pin_EndOfStream (DShowPin *); -long ff_dshow_pin_BeginFlush (DShowPin *); -long ff_dshow_pin_EndFlush (DShowPin *); -long ff_dshow_pin_NewSegment (DShowPin *, REFERENCE_TIME, REFERENCE_TIME, double); +long WINAPI ff_dshow_pin_QueryInterface (DShowPin *, const GUID *, void **); +unsigned long WINAPI ff_dshow_pin_AddRef (DShowPin *); +unsigned long WINAPI ff_dshow_pin_Release (DShowPin *); +long WINAPI ff_dshow_pin_Connect (DShowPin *, IPin *, const AM_MEDIA_TYPE *); +long WINAPI ff_dshow_pin_ReceiveConnection (DShowPin *, IPin *, const AM_MEDIA_TYPE *); +long WINAPI ff_dshow_pin_Disconnect (DShowPin *); +long WINAPI ff_dshow_pin_ConnectedTo (DShowPin *, IPin **); +long WINAPI ff_dshow_pin_ConnectionMediaType (DShowPin *, AM_MEDIA_TYPE *); +long WINAPI ff_dshow_pin_QueryPinInfo (DShowPin *, PIN_INFO *); +long WINAPI ff_dshow_pin_QueryDirection (DShowPin *, PIN_DIRECTION *); +long WINAPI ff_dshow_pin_QueryId (DShowPin *, wchar_t **); +long WINAPI ff_dshow_pin_QueryAccept (DShowPin *, const AM_MEDIA_TYPE *); +long WINAPI ff_dshow_pin_EnumMediaTypes (DShowPin *, IEnumMediaTypes **); +long WINAPI ff_dshow_pin_QueryInternalConnections(DShowPin *, IPin **, unsigned long *); +long WINAPI ff_dshow_pin_EndOfStream (DShowPin *); +long WINAPI ff_dshow_pin_BeginFlush (DShowPin *); +long WINAPI ff_dshow_pin_EndFlush (DShowPin *); +long WINAPI ff_dshow_pin_NewSegment (DShowPin *, REFERENCE_TIME, REFERENCE_TIME, double); -long ff_dshow_meminputpin_QueryInterface (DShowMemInputPin *, const GUID *, void **); -unsigned long ff_dshow_meminputpin_AddRef (DShowMemInputPin *); -unsigned long ff_dshow_meminputpin_Release (DShowMemInputPin *); -long ff_dshow_meminputpin_GetAllocator (DShowMemInputPin *, IMemAllocator **); -long ff_dshow_meminputpin_NotifyAllocator (DShowMemInputPin *, IMemAllocator *, BOOL); -long ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *, ALLOCATOR_PROPERTIES *); -long ff_dshow_meminputpin_Receive (DShowMemInputPin *, IMediaSample *); -long ff_dshow_meminputpin_ReceiveMultiple (DShowMemInputPin *, IMediaSample **, long, long *); -long ff_dshow_meminputpin_ReceiveCanBlock (DShowMemInputPin *); +long WINAPI ff_dshow_meminputpin_QueryInterface (DShowMemInputPin *, const GUID *, void **); +unsigned long WINAPI ff_dshow_meminputpin_AddRef (DShowMemInputPin *); +unsigned long WINAPI ff_dshow_meminputpin_Release (DShowMemInputPin *); +long WINAPI ff_dshow_meminputpin_GetAllocator (DShowMemInputPin *, IMemAllocator **); +long WINAPI ff_dshow_meminputpin_NotifyAllocator (DShowMemInputPin *, IMemAllocator *, BOOL); +long WINAPI ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *, ALLOCATOR_PROPERTIES *); +long WINAPI ff_dshow_meminputpin_Receive (DShowMemInputPin *, IMediaSample *); +long WINAPI ff_dshow_meminputpin_ReceiveMultiple (DShowMemInputPin *, IMediaSample **, long, long *); +long WINAPI ff_dshow_meminputpin_ReceiveCanBlock (DShowMemInputPin *); void ff_dshow_pin_Destroy(DShowPin *); DShowPin *ff_dshow_pin_Create (DShowFilter *filter); @@ -212,13 +212,13 @@ struct DShowEnumPins { DShowFilter *filter; }; -long ff_dshow_enumpins_QueryInterface(DShowEnumPins *, const GUID *, void **); -unsigned long ff_dshow_enumpins_AddRef (DShowEnumPins *); -unsigned long ff_dshow_enumpins_Release (DShowEnumPins *); -long ff_dshow_enumpins_Next (DShowEnumPins *, unsigned long, IPin **, unsigned long *); -long ff_dshow_enumpins_Skip (DShowEnumPins *, unsigned long); -long ff_dshow_enumpins_Reset (DShowEnumPins *); -long ff_dshow_enumpins_Clone (DShowEnumPins *, DShowEnumPins **); +long WINAPI ff_dshow_enumpins_QueryInterface(DShowEnumPins *, const GUID *, void **); +unsigned long WINAPI ff_dshow_enumpins_AddRef (DShowEnumPins *); +unsigned long WINAPI ff_dshow_enumpins_Release (DShowEnumPins *); +long WINAPI ff_dshow_enumpins_Next (DShowEnumPins *, unsigned long, IPin **, unsigned long *); +long WINAPI ff_dshow_enumpins_Skip (DShowEnumPins *, unsigned long); +long WINAPI ff_dshow_enumpins_Reset (DShowEnumPins *); +long WINAPI ff_dshow_enumpins_Clone (DShowEnumPins *, DShowEnumPins **); void ff_dshow_enumpins_Destroy(DShowEnumPins *); DShowEnumPins *ff_dshow_enumpins_Create (DShowPin *pin, DShowFilter *filter); @@ -233,13 +233,13 @@ struct DShowEnumMediaTypes { AM_MEDIA_TYPE type; }; -long ff_dshow_enummediatypes_QueryInterface(DShowEnumMediaTypes *, const GUID *, void **); -unsigned long ff_dshow_enummediatypes_AddRef (DShowEnumMediaTypes *); -unsigned long ff_dshow_enummediatypes_Release (DShowEnumMediaTypes *); -long ff_dshow_enummediatypes_Next (DShowEnumMediaTypes *, unsigned long, AM_MEDIA_TYPE **, unsigned long *); -long ff_dshow_enummediatypes_Skip (DShowEnumMediaTypes *, unsigned long); -long ff_dshow_enummediatypes_Reset (DShowEnumMediaTypes *); -long ff_dshow_enummediatypes_Clone (DShowEnumMediaTypes *, DShowEnumMediaTypes **); +long WINAPI ff_dshow_enummediatypes_QueryInterface(DShowEnumMediaTypes *, const GUID *, void **); +unsigned long WINAPI ff_dshow_enummediatypes_AddRef (DShowEnumMediaTypes *); +unsigned long WINAPI ff_dshow_enummediatypes_Release (DShowEnumMediaTypes *); +long WINAPI ff_dshow_enummediatypes_Next (DShowEnumMediaTypes *, unsigned long, AM_MEDIA_TYPE **, unsigned long *); +long WINAPI ff_dshow_enummediatypes_Skip (DShowEnumMediaTypes *, unsigned long); +long WINAPI ff_dshow_enummediatypes_Reset (DShowEnumMediaTypes *); +long WINAPI ff_dshow_enummediatypes_Clone (DShowEnumMediaTypes *, DShowEnumMediaTypes **); void ff_dshow_enummediatypes_Destroy(DShowEnumMediaTypes *); DShowEnumMediaTypes *ff_dshow_enummediatypes_Create(const AM_MEDIA_TYPE *type); @@ -262,21 +262,21 @@ struct DShowFilter { void (*callback)(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType type); }; -long ff_dshow_filter_QueryInterface (DShowFilter *, const GUID *, void **); -unsigned long ff_dshow_filter_AddRef (DShowFilter *); -unsigned long ff_dshow_filter_Release (DShowFilter *); -long ff_dshow_filter_GetClassID (DShowFilter *, CLSID *); -long ff_dshow_filter_Stop (DShowFilter *); -long ff_dshow_filter_Pause (DShowFilter *); -long ff_dshow_filter_Run (DShowFilter *, REFERENCE_TIME); -long ff_dshow_filter_GetState (DShowFilter *, DWORD, FILTER_STATE *); -long ff_dshow_filter_SetSyncSource (DShowFilter *, IReferenceClock *); -long ff_dshow_filter_GetSyncSource (DShowFilter *, IReferenceClock **); -long ff_dshow_filter_EnumPins (DShowFilter *, IEnumPins **); -long ff_dshow_filter_FindPin (DShowFilter *, const wchar_t *, IPin **); -long ff_dshow_filter_QueryFilterInfo(DShowFilter *, FILTER_INFO *); -long ff_dshow_filter_JoinFilterGraph(DShowFilter *, IFilterGraph *, const wchar_t *); -long ff_dshow_filter_QueryVendorInfo(DShowFilter *, wchar_t **); +long WINAPI ff_dshow_filter_QueryInterface (DShowFilter *, const GUID *, void **); +unsigned long WINAPI ff_dshow_filter_AddRef (DShowFilter *); +unsigned long WINAPI ff_dshow_filter_Release (DShowFilter *); +long WINAPI ff_dshow_filter_GetClassID (DShowFilter *, CLSID *); +long WINAPI ff_dshow_filter_Stop (DShowFilter *); +long WINAPI ff_dshow_filter_Pause (DShowFilter *); +long WINAPI ff_dshow_filter_Run (DShowFilter *, REFERENCE_TIME); +long WINAPI ff_dshow_filter_GetState (DShowFilter *, DWORD, FILTER_STATE *); +long WINAPI ff_dshow_filter_SetSyncSource (DShowFilter *, IReferenceClock *); +long WINAPI ff_dshow_filter_GetSyncSource (DShowFilter *, IReferenceClock **); +long WINAPI ff_dshow_filter_EnumPins (DShowFilter *, IEnumPins **); +long WINAPI ff_dshow_filter_FindPin (DShowFilter *, const wchar_t *, IPin **); +long WINAPI ff_dshow_filter_QueryFilterInfo(DShowFilter *, FILTER_INFO *); +long WINAPI ff_dshow_filter_JoinFilterGraph(DShowFilter *, IFilterGraph *, const wchar_t *); +long WINAPI ff_dshow_filter_QueryVendorInfo(DShowFilter *, wchar_t **); void ff_dshow_filter_Destroy(DShowFilter *); DShowFilter *ff_dshow_filter_Create (void *, void *, enum dshowDeviceType); diff --git a/libavdevice/dshow_enummediatypes.c b/libavdevice/dshow_enummediatypes.c index 82944507f6..4cb7057e17 100644 --- a/libavdevice/dshow_enummediatypes.c +++ b/libavdevice/dshow_enummediatypes.c @@ -26,7 +26,7 @@ DECLARE_QUERYINTERFACE(enummediatypes, DShowEnumMediaTypes, DECLARE_ADDREF(enummediatypes, DShowEnumMediaTypes) DECLARE_RELEASE(enummediatypes, DShowEnumMediaTypes) -long ff_dshow_enummediatypes_Next(DShowEnumMediaTypes *this, unsigned long n, +long WINAPI ff_dshow_enummediatypes_Next(DShowEnumMediaTypes *this, unsigned long n, AM_MEDIA_TYPE **types, unsigned long *fetched) { int count = 0; @@ -50,20 +50,20 @@ long ff_dshow_enummediatypes_Next(DShowEnumMediaTypes *this, unsigned long n, return S_FALSE; return S_OK; } -long ff_dshow_enummediatypes_Skip(DShowEnumMediaTypes *this, unsigned long n) +long WINAPI ff_dshow_enummediatypes_Skip(DShowEnumMediaTypes *this, unsigned long n) { dshowdebug("ff_dshow_enummediatypes_Skip(%p)\n", this); if (n) /* Any skip will always fall outside of the only valid type. */ return S_FALSE; return S_OK; } -long ff_dshow_enummediatypes_Reset(DShowEnumMediaTypes *this) +long WINAPI ff_dshow_enummediatypes_Reset(DShowEnumMediaTypes *this) { dshowdebug("ff_dshow_enummediatypes_Reset(%p)\n", this); this->pos = 0; return S_OK; } -long ff_dshow_enummediatypes_Clone(DShowEnumMediaTypes *this, DShowEnumMediaTypes **enums) +long WINAPI ff_dshow_enummediatypes_Clone(DShowEnumMediaTypes *this, DShowEnumMediaTypes **enums) { DShowEnumMediaTypes *new; dshowdebug("ff_dshow_enummediatypes_Clone(%p)\n", this); diff --git a/libavdevice/dshow_enumpins.c b/libavdevice/dshow_enumpins.c index 6bf59928f9..759b589ade 100644 --- a/libavdevice/dshow_enumpins.c +++ b/libavdevice/dshow_enumpins.c @@ -26,7 +26,7 @@ DECLARE_QUERYINTERFACE(enumpins, DShowEnumPins, DECLARE_ADDREF(enumpins, DShowEnumPins) DECLARE_RELEASE(enumpins, DShowEnumPins) -long ff_dshow_enumpins_Next(DShowEnumPins *this, unsigned long n, IPin **pins, +long WINAPI ff_dshow_enumpins_Next(DShowEnumPins *this, unsigned long n, IPin **pins, unsigned long *fetched) { int count = 0; @@ -45,20 +45,20 @@ long ff_dshow_enumpins_Next(DShowEnumPins *this, unsigned long n, IPin **pins, return S_FALSE; return S_OK; } -long ff_dshow_enumpins_Skip(DShowEnumPins *this, unsigned long n) +long WINAPI ff_dshow_enumpins_Skip(DShowEnumPins *this, unsigned long n) { dshowdebug("ff_dshow_enumpins_Skip(%p)\n", this); if (n) /* Any skip will always fall outside of the only valid pin. */ return S_FALSE; return S_OK; } -long ff_dshow_enumpins_Reset(DShowEnumPins *this) +long WINAPI ff_dshow_enumpins_Reset(DShowEnumPins *this) { dshowdebug("ff_dshow_enumpins_Reset(%p)\n", this); this->pos = 0; return S_OK; } -long ff_dshow_enumpins_Clone(DShowEnumPins *this, DShowEnumPins **pins) +long WINAPI ff_dshow_enumpins_Clone(DShowEnumPins *this, DShowEnumPins **pins) { DShowEnumPins *new; dshowdebug("ff_dshow_enumpins_Clone(%p)\n", this); diff --git a/libavdevice/dshow_filter.c b/libavdevice/dshow_filter.c index 61e057a836..4642ac077c 100644 --- a/libavdevice/dshow_filter.c +++ b/libavdevice/dshow_filter.c @@ -26,32 +26,32 @@ DECLARE_QUERYINTERFACE(filter, DShowFilter, DECLARE_ADDREF(filter, DShowFilter) DECLARE_RELEASE(filter, DShowFilter) -long ff_dshow_filter_GetClassID(DShowFilter *this, CLSID *id) +long WINAPI ff_dshow_filter_GetClassID(DShowFilter *this, CLSID *id) { dshowdebug("ff_dshow_filter_GetClassID(%p)\n", this); /* I'm not creating a ClassID just for this. */ return E_FAIL; } -long ff_dshow_filter_Stop(DShowFilter *this) +long WINAPI ff_dshow_filter_Stop(DShowFilter *this) { dshowdebug("ff_dshow_filter_Stop(%p)\n", this); this->state = State_Stopped; return S_OK; } -long ff_dshow_filter_Pause(DShowFilter *this) +long WINAPI ff_dshow_filter_Pause(DShowFilter *this) { dshowdebug("ff_dshow_filter_Pause(%p)\n", this); this->state = State_Paused; return S_OK; } -long ff_dshow_filter_Run(DShowFilter *this, REFERENCE_TIME start) +long WINAPI ff_dshow_filter_Run(DShowFilter *this, REFERENCE_TIME start) { dshowdebug("ff_dshow_filter_Run(%p) %"PRId64"\n", this, start); this->state = State_Running; this->start_time = start; return S_OK; } -long ff_dshow_filter_GetState(DShowFilter *this, DWORD ms, FILTER_STATE *state) +long WINAPI ff_dshow_filter_GetState(DShowFilter *this, DWORD ms, FILTER_STATE *state) { dshowdebug("ff_dshow_filter_GetState(%p)\n", this); if (!state) @@ -59,7 +59,7 @@ long ff_dshow_filter_GetState(DShowFilter *this, DWORD ms, FILTER_STATE *state) *state = this->state; return S_OK; } -long ff_dshow_filter_SetSyncSource(DShowFilter *this, IReferenceClock *clock) +long WINAPI ff_dshow_filter_SetSyncSource(DShowFilter *this, IReferenceClock *clock) { dshowdebug("ff_dshow_filter_SetSyncSource(%p)\n", this); @@ -73,7 +73,7 @@ long ff_dshow_filter_SetSyncSource(DShowFilter *this, IReferenceClock *clock) return S_OK; } -long ff_dshow_filter_GetSyncSource(DShowFilter *this, IReferenceClock **clock) +long WINAPI ff_dshow_filter_GetSyncSource(DShowFilter *this, IReferenceClock **clock) { dshowdebug("ff_dshow_filter_GetSyncSource(%p)\n", this); @@ -85,7 +85,7 @@ long ff_dshow_filter_GetSyncSource(DShowFilter *this, IReferenceClock **clock) return S_OK; } -long ff_dshow_filter_EnumPins(DShowFilter *this, IEnumPins **enumpin) +long WINAPI ff_dshow_filter_EnumPins(DShowFilter *this, IEnumPins **enumpin) { DShowEnumPins *new; dshowdebug("ff_dshow_filter_EnumPins(%p)\n", this); @@ -99,7 +99,7 @@ long ff_dshow_filter_EnumPins(DShowFilter *this, IEnumPins **enumpin) *enumpin = (IEnumPins *) new; return S_OK; } -long ff_dshow_filter_FindPin(DShowFilter *this, const wchar_t *id, IPin **pin) +long WINAPI ff_dshow_filter_FindPin(DShowFilter *this, const wchar_t *id, IPin **pin) { DShowPin *found = NULL; dshowdebug("ff_dshow_filter_FindPin(%p)\n", this); @@ -116,7 +116,7 @@ long ff_dshow_filter_FindPin(DShowFilter *this, const wchar_t *id, IPin **pin) return S_OK; } -long ff_dshow_filter_QueryFilterInfo(DShowFilter *this, FILTER_INFO *info) +long WINAPI ff_dshow_filter_QueryFilterInfo(DShowFilter *this, FILTER_INFO *info) { dshowdebug("ff_dshow_filter_QueryFilterInfo(%p)\n", this); @@ -128,7 +128,7 @@ long ff_dshow_filter_QueryFilterInfo(DShowFilter *this, FILTER_INFO *info) return S_OK; } -long ff_dshow_filter_JoinFilterGraph(DShowFilter *this, IFilterGraph *graph, +long WINAPI ff_dshow_filter_JoinFilterGraph(DShowFilter *this, IFilterGraph *graph, const wchar_t *name) { dshowdebug("ff_dshow_filter_JoinFilterGraph(%p)\n", this); @@ -139,7 +139,7 @@ long ff_dshow_filter_JoinFilterGraph(DShowFilter *this, IFilterGraph *graph, return S_OK; } -long ff_dshow_filter_QueryVendorInfo(DShowFilter *this, wchar_t **info) +long WINAPI ff_dshow_filter_QueryVendorInfo(DShowFilter *this, wchar_t **info) { dshowdebug("ff_dshow_filter_QueryVendorInfo(%p)\n", this); diff --git a/libavdevice/dshow_pin.c b/libavdevice/dshow_pin.c index 2d1fa0e882..f846b68918 100644 --- a/libavdevice/dshow_pin.c +++ b/libavdevice/dshow_pin.c @@ -29,13 +29,13 @@ DECLARE_QUERYINTERFACE(pin, DShowPin, DECLARE_ADDREF(pin, DShowPin) DECLARE_RELEASE(pin, DShowPin) -long ff_dshow_pin_Connect(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type) +long WINAPI ff_dshow_pin_Connect(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type) { dshowdebug("ff_dshow_pin_Connect(%p, %p, %p)\n", this, pin, type); /* Input pins receive connections. */ return S_FALSE; } -long ff_dshow_pin_ReceiveConnection(DShowPin *this, IPin *pin, +long WINAPI ff_dshow_pin_ReceiveConnection(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type) { enum dshowDeviceType devtype = this->filter->type; @@ -62,7 +62,7 @@ long ff_dshow_pin_ReceiveConnection(DShowPin *this, IPin *pin, return S_OK; } -long ff_dshow_pin_Disconnect(DShowPin *this) +long WINAPI ff_dshow_pin_Disconnect(DShowPin *this) { dshowdebug("ff_dshow_pin_Disconnect(%p)\n", this); @@ -75,7 +75,7 @@ long ff_dshow_pin_Disconnect(DShowPin *this) return S_OK; } -long ff_dshow_pin_ConnectedTo(DShowPin *this, IPin **pin) +long WINAPI ff_dshow_pin_ConnectedTo(DShowPin *this, IPin **pin) { dshowdebug("ff_dshow_pin_ConnectedTo(%p)\n", this); @@ -88,7 +88,7 @@ long ff_dshow_pin_ConnectedTo(DShowPin *this, IPin **pin) return S_OK; } -long ff_dshow_pin_ConnectionMediaType(DShowPin *this, AM_MEDIA_TYPE *type) +long WINAPI ff_dshow_pin_ConnectionMediaType(DShowPin *this, AM_MEDIA_TYPE *type) { dshowdebug("ff_dshow_pin_ConnectionMediaType(%p)\n", this); @@ -99,7 +99,7 @@ long ff_dshow_pin_ConnectionMediaType(DShowPin *this, AM_MEDIA_TYPE *type) return ff_copy_dshow_media_type(type, &this->type); } -long ff_dshow_pin_QueryPinInfo(DShowPin *this, PIN_INFO *info) +long WINAPI ff_dshow_pin_QueryPinInfo(DShowPin *this, PIN_INFO *info) { dshowdebug("ff_dshow_pin_QueryPinInfo(%p)\n", this); @@ -115,7 +115,7 @@ long ff_dshow_pin_QueryPinInfo(DShowPin *this, PIN_INFO *info) return S_OK; } -long ff_dshow_pin_QueryDirection(DShowPin *this, PIN_DIRECTION *dir) +long WINAPI ff_dshow_pin_QueryDirection(DShowPin *this, PIN_DIRECTION *dir) { dshowdebug("ff_dshow_pin_QueryDirection(%p)\n", this); if (!dir) @@ -123,7 +123,7 @@ long ff_dshow_pin_QueryDirection(DShowPin *this, PIN_DIRECTION *dir) *dir = PINDIR_INPUT; return S_OK; } -long ff_dshow_pin_QueryId(DShowPin *this, wchar_t **id) +long WINAPI ff_dshow_pin_QueryId(DShowPin *this, wchar_t **id) { dshowdebug("ff_dshow_pin_QueryId(%p)\n", this); @@ -134,12 +134,12 @@ long ff_dshow_pin_QueryId(DShowPin *this, wchar_t **id) return S_OK; } -long ff_dshow_pin_QueryAccept(DShowPin *this, const AM_MEDIA_TYPE *type) +long WINAPI ff_dshow_pin_QueryAccept(DShowPin *this, const AM_MEDIA_TYPE *type) { dshowdebug("ff_dshow_pin_QueryAccept(%p)\n", this); return S_FALSE; } -long ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes) +long WINAPI ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes) { const AM_MEDIA_TYPE *type = NULL; DShowEnumMediaTypes *new; @@ -154,31 +154,31 @@ long ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes) *enumtypes = (IEnumMediaTypes *) new; return S_OK; } -long ff_dshow_pin_QueryInternalConnections(DShowPin *this, IPin **pin, +long WINAPI ff_dshow_pin_QueryInternalConnections(DShowPin *this, IPin **pin, unsigned long *npin) { dshowdebug("ff_dshow_pin_QueryInternalConnections(%p)\n", this); return E_NOTIMPL; } -long ff_dshow_pin_EndOfStream(DShowPin *this) +long WINAPI ff_dshow_pin_EndOfStream(DShowPin *this) { dshowdebug("ff_dshow_pin_EndOfStream(%p)\n", this); /* I don't care. */ return S_OK; } -long ff_dshow_pin_BeginFlush(DShowPin *this) +long WINAPI ff_dshow_pin_BeginFlush(DShowPin *this) { dshowdebug("ff_dshow_pin_BeginFlush(%p)\n", this); /* I don't care. */ return S_OK; } -long ff_dshow_pin_EndFlush(DShowPin *this) +long WINAPI ff_dshow_pin_EndFlush(DShowPin *this) { dshowdebug("ff_dshow_pin_EndFlush(%p)\n", this); /* I don't care. */ return S_OK; } -long ff_dshow_pin_NewSegment(DShowPin *this, REFERENCE_TIME start, REFERENCE_TIME stop, +long WINAPI ff_dshow_pin_NewSegment(DShowPin *this, REFERENCE_TIME start, REFERENCE_TIME stop, double rate) { dshowdebug("ff_dshow_pin_NewSegment(%p)\n", this); @@ -250,43 +250,43 @@ DECLARE_DESTROY(pin, DShowPin, ff_dshow_pin_Free) /***************************************************************************** * DShowMemInputPin ****************************************************************************/ -long ff_dshow_meminputpin_QueryInterface(DShowMemInputPin *this, const GUID *riid, +long WINAPI ff_dshow_meminputpin_QueryInterface(DShowMemInputPin *this, const GUID *riid, void **ppvObject) { DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); dshowdebug("ff_dshow_meminputpin_QueryInterface(%p)\n", this); return ff_dshow_pin_QueryInterface(pin, riid, ppvObject); } -unsigned long ff_dshow_meminputpin_AddRef(DShowMemInputPin *this) +unsigned long WINAPI ff_dshow_meminputpin_AddRef(DShowMemInputPin *this) { DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); dshowdebug("ff_dshow_meminputpin_AddRef(%p)\n", this); return ff_dshow_pin_AddRef(pin); } -unsigned long ff_dshow_meminputpin_Release(DShowMemInputPin *this) +unsigned long WINAPI ff_dshow_meminputpin_Release(DShowMemInputPin *this) { DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); dshowdebug("ff_dshow_meminputpin_Release(%p)\n", this); return ff_dshow_pin_Release(pin); } -long ff_dshow_meminputpin_GetAllocator(DShowMemInputPin *this, IMemAllocator **alloc) +long WINAPI ff_dshow_meminputpin_GetAllocator(DShowMemInputPin *this, IMemAllocator **alloc) { dshowdebug("ff_dshow_meminputpin_GetAllocator(%p)\n", this); return VFW_E_NO_ALLOCATOR; } -long ff_dshow_meminputpin_NotifyAllocator(DShowMemInputPin *this, IMemAllocator *alloc, +long WINAPI ff_dshow_meminputpin_NotifyAllocator(DShowMemInputPin *this, IMemAllocator *alloc, BOOL rdwr) { dshowdebug("ff_dshow_meminputpin_NotifyAllocator(%p)\n", this); return S_OK; } -long ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *this, +long WINAPI ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *this, ALLOCATOR_PROPERTIES *props) { dshowdebug("ff_dshow_meminputpin_GetAllocatorRequirements(%p)\n", this); return E_NOTIMPL; } -long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) +long WINAPI ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) { DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); enum dshowDeviceType devtype = pin->filter->type; @@ -354,7 +354,7 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) return S_OK; } -long ff_dshow_meminputpin_ReceiveMultiple(DShowMemInputPin *this, +long WINAPI ff_dshow_meminputpin_ReceiveMultiple(DShowMemInputPin *this, IMediaSample **samples, long n, long *nproc) { int i; @@ -366,7 +366,7 @@ long ff_dshow_meminputpin_ReceiveMultiple(DShowMemInputPin *this, *nproc = n; return S_OK; } -long ff_dshow_meminputpin_ReceiveCanBlock(DShowMemInputPin *this) +long WINAPI ff_dshow_meminputpin_ReceiveCanBlock(DShowMemInputPin *this) { dshowdebug("ff_dshow_meminputpin_ReceiveCanBlock(%p)\n", this); /* I swear I will not block. */ From 25518f2aa6821cd37bb20b53853eb1b2ef95b755 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Sun, 2 Jan 2022 10:49:39 +0100 Subject: [PATCH 26/38] avdevice/dshow: only set pin format if wanted Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 4b6887881d..f2d95fa470 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -1046,7 +1046,7 @@ next: // format based on the VIDEOINFOHEADER format. // NB: this never applies to an audio format because // previous_match_type always NULL in that case - if (!format_set && previous_match_type) { + if (pformat_set && !format_set && previous_match_type) { if (IAMStreamConfig_SetFormat(config, previous_match_type) == S_OK) format_set = 1; } From e84d8ba44141b55f2b28e0ad3b597d2e7d422336 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Sun, 2 Jan 2022 10:49:40 +0100 Subject: [PATCH 27/38] avdevice/dshow: ensure pin's default format is set Fixes regression in a1c4929f: there apparently are devices out there that expose a pin default format that has parameters outside the capabilities of any of the formats exposed on the pin (sic?). The VirtualCam plugin (v 2.0.5) of OBS-Studio (v 27.1.3) is such a device. Now when a default format was found, but not selected when iterating all formats, fall back to directly setting the default format. Signed-off-by: Diederick Niehorster Reviewed-by: Roger Pack --- libavdevice/dshow.c | 88 +++++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 34 deletions(-) diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index f2d95fa470..a435ae1807 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -758,6 +758,31 @@ static struct dshow_format_info *dshow_get_format_info(AM_MEDIA_TYPE *type) return fmt_info; } +static void dshow_get_default_format(IPin *pin, IAMStreamConfig *config, enum dshowDeviceType devtype, AM_MEDIA_TYPE **type) +{ + HRESULT hr; + + if ((hr = IAMStreamConfig_GetFormat(config, type)) != S_OK) { + if (hr == E_NOTIMPL || !IsEqualGUID(&(*type)->majortype, devtype == VideoDevice ? &MEDIATYPE_Video : &MEDIATYPE_Audio)) { + // default not available or of wrong type, + // fall back to iterating exposed formats + // until one of the right type is found + IEnumMediaTypes* types = NULL; + if (IPin_EnumMediaTypes(pin, &types) != S_OK) + return; + IEnumMediaTypes_Reset(types); + while (IEnumMediaTypes_Next(types, 1, type, NULL) == S_OK) { + if (IsEqualGUID(&(*type)->majortype, devtype == VideoDevice ? &MEDIATYPE_Video : &MEDIATYPE_Audio)) { + break; + } + CoTaskMemFree(*type); + *type = NULL; + } + IEnumMediaTypes_Release(types); + } + } +} + /** * Cycle through available formats available from the specified pin, * try to set parameters specified through AVOptions, or the pin's @@ -813,32 +838,11 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, use_default = !dshow_should_set_format(avctx, devtype); if (use_default && pformat_set) { - HRESULT hr; - // get default - if ((hr = IAMStreamConfig_GetFormat(config, &type)) != S_OK) { - if (hr == E_NOTIMPL || !IsEqualGUID(&type->majortype, devtype==VideoDevice ? &MEDIATYPE_Video : &MEDIATYPE_Audio)) { - // default not available or of wrong type, - // fall back to iterating exposed formats - // until one of the right type is found - IEnumMediaTypes *types = NULL; - if (IPin_EnumMediaTypes(pin, &types) != S_OK) - goto end; - IEnumMediaTypes_Reset(types); - while (IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) { - if (IsEqualGUID(&type->majortype, devtype==VideoDevice ? &MEDIATYPE_Video : &MEDIATYPE_Audio)) { - break; - } - CoTaskMemFree(type); - type = NULL; - } - IEnumMediaTypes_Release(types); - } - - if (!type) - // this pin does not expose any formats of the expected type - goto end; - } + dshow_get_default_format(pin, config, devtype, &type); + if (!type) + // this pin does not expose any formats of the expected type + goto end; if (type) { // interrogate default format, so we know what to search for below @@ -1040,15 +1044,31 @@ next: CoTaskMemFree(type); type = NULL; } - // previously found a matching VIDEOINFOHEADER format and stored - // it for safe keeping. Searching further for a matching - // VIDEOINFOHEADER2 format yielded nothing. So set the pin's - // format based on the VIDEOINFOHEADER format. - // NB: this never applies to an audio format because - // previous_match_type always NULL in that case - if (pformat_set && !format_set && previous_match_type) { - if (IAMStreamConfig_SetFormat(config, previous_match_type) == S_OK) - format_set = 1; + + // set the pin's format, if wanted + if (pformat_set && !format_set) { + if (previous_match_type) { + // previously found a matching VIDEOINFOHEADER format and stored + // it for safe keeping. Searching further for a matching + // VIDEOINFOHEADER2 format yielded nothing. So set the pin's + // format based on the VIDEOINFOHEADER format. + // NB: this never applies to an audio format because + // previous_match_type always NULL in that case + if (IAMStreamConfig_SetFormat(config, previous_match_type) == S_OK) + format_set = 1; + } + else if (use_default) { + // default format returned by device apparently was not contained + // in the capabilities of any of the formats returned by the device + // (sic?). Fall back to directly setting the default format + dshow_get_default_format(pin, config, devtype, &type); + if (IAMStreamConfig_SetFormat(config, type) == S_OK) + format_set = 1; + if (type && type->pbFormat) + CoTaskMemFree(type->pbFormat); + CoTaskMemFree(type); + type = NULL; + } } end: From 3d53cefb49289e5e27b652e13623017b05ace452 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 1 Mar 2021 18:34:26 +0100 Subject: [PATCH 28/38] avcodec/raw: Reduce number of avpriv symbols libavcodec currently exports four avpriv symbols that deal with PixelFormatTags: avpriv_get_raw_pix_fmt_tags, avpriv_find_pix_fmt, avpriv_pix_fmt_bps_avi and avpriv_pix_fmt_bps_mov. The latter two are lists of PixelFormatTags, the former returns such a list and the second searches a list for a pixel format that matches a given fourcc; only one of the aforementioned three lists is ever searched. Yet for avpriv_pix_fmt_bps_avi, avpriv_pix_fmt_bps_mov and avpriv_find_pix_fmt the overhead of exporting these functions actually exceeds the size of said objects (at least for ELF; the following numbers are for x64 Ubuntu 20.10): The code size of avpriv_find_pix_fmt is small (GCC 10.2 37B, Clang 11 41B), yet exporting it adds a 20B string for the name alone to the exporting as well as to each importing library; there is more: Four bytes in the exporting libraries .gnu.hash; two bytes each for the exporting as well as each importing libraries .gnu.version; 24B in the exporting as well as each importing libraries .dynsym; 16B+24B for an entry in .plt as well as the accompanying relocation entry in .rela.plt for each importing library. The overhead for the lists is similar: The strings are 23B and the .plt+.rela.plt pair is replaced by 8B+24B for an entry in .got and a relocation entry in .rela.dyn. These lists have a size of 80 resp. 72 bytes. Yet for ff_raw_pix_fmt_tags, exporting it is advantageous compared to duplicating it into libavformat and potentially libavdevice. Therefore this commit replaces all library uses of the four symbols with a single function that is exported for shared builds. It has an enum parameter to choose the desired list besides the parameter for the fourcc. New lists can be supported with new enum values. Unfortunately, avpriv_get_raw_pix_fmt_tags could not be removed, as the fourcc2pixfmt tool uses the table of raw pix fmts. No other user of this function remains. Signed-off-by: Andreas Rheinhardt --- libavcodec/raw.c | 40 +++++++++++++++++++++++++++++++++++----- libavcodec/raw.h | 13 +++++++------ libavcodec/rawdec.c | 8 ++++---- libavcodec/utils.c | 11 ----------- libavdevice/dshow.c | 2 +- libavformat/avienc.c | 2 +- libavformat/demux.c | 2 +- libavformat/movenc.c | 2 +- 8 files changed, 50 insertions(+), 30 deletions(-) diff --git a/libavcodec/raw.c b/libavcodec/raw.c index 079d5c5d10..5efc1eb465 100644 --- a/libavcodec/raw.c +++ b/libavcodec/raw.c @@ -28,7 +28,7 @@ #include "raw.h" #include "libavutil/common.h" -const PixelFormatTag ff_raw_pix_fmt_tags[] = { +static const PixelFormatTag raw_pix_fmt_tags[] = { { AV_PIX_FMT_YUV420P, MKTAG('I', '4', '2', '0') }, /* Planar formats */ { AV_PIX_FMT_YUV420P, MKTAG('I', 'Y', 'U', 'V') }, { AV_PIX_FMT_YUV420P, MKTAG('y', 'v', '1', '2') }, @@ -299,12 +299,12 @@ const PixelFormatTag ff_raw_pix_fmt_tags[] = { const struct PixelFormatTag *avpriv_get_raw_pix_fmt_tags(void) { - return ff_raw_pix_fmt_tags; + return raw_pix_fmt_tags; } unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat fmt) { - const PixelFormatTag *tags = ff_raw_pix_fmt_tags; + const PixelFormatTag *tags = raw_pix_fmt_tags; while (tags->pix_fmt >= 0) { if (tags->pix_fmt == fmt) return tags->fourcc; @@ -313,7 +313,7 @@ unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat fmt) return 0; } -const PixelFormatTag avpriv_pix_fmt_bps_avi[] = { +static const PixelFormatTag pix_fmt_bps_avi[] = { { AV_PIX_FMT_PAL8, 1 }, { AV_PIX_FMT_PAL8, 2 }, { AV_PIX_FMT_PAL8, 4 }, @@ -326,7 +326,7 @@ const PixelFormatTag avpriv_pix_fmt_bps_avi[] = { { AV_PIX_FMT_NONE, 0 }, }; -const PixelFormatTag avpriv_pix_fmt_bps_mov[] = { +static const PixelFormatTag pix_fmt_bps_mov[] = { { AV_PIX_FMT_PAL8, 1 }, { AV_PIX_FMT_PAL8, 2 }, { AV_PIX_FMT_PAL8, 4 }, @@ -337,3 +337,33 @@ const PixelFormatTag avpriv_pix_fmt_bps_mov[] = { { AV_PIX_FMT_PAL8, 33 }, { AV_PIX_FMT_NONE, 0 }, }; + +static enum AVPixelFormat find_pix_fmt(const PixelFormatTag *tags, + unsigned int fourcc) +{ + while (tags->pix_fmt != AV_PIX_FMT_NONE) { + if (tags->fourcc == fourcc) + return tags->pix_fmt; + tags++; + } + return AV_PIX_FMT_NONE; +} + +enum AVPixelFormat avpriv_pix_fmt_find(enum PixelFormatTagLists list, + unsigned fourcc) +{ + const PixelFormatTag *tags; + + switch (list) { + case PIX_FMT_LIST_RAW: + tags = raw_pix_fmt_tags; + break; + case PIX_FMT_LIST_AVI: + tags = pix_fmt_bps_avi; + break; + case PIX_FMT_LIST_MOV: + tags = pix_fmt_bps_mov; + break; + } + return find_pix_fmt(tags, fourcc); +} diff --git a/libavcodec/raw.h b/libavcodec/raw.h index 6a041690b1..9a4ddef8fc 100644 --- a/libavcodec/raw.h +++ b/libavcodec/raw.h @@ -28,20 +28,21 @@ #define AVCODEC_RAW_H #include "libavutil/pixfmt.h" -#include "internal.h" typedef struct PixelFormatTag { enum AVPixelFormat pix_fmt; unsigned int fourcc; } PixelFormatTag; -extern const PixelFormatTag ff_raw_pix_fmt_tags[]; // exposed through avpriv_get_raw_pix_fmt_tags() - const struct PixelFormatTag *avpriv_get_raw_pix_fmt_tags(void); -enum AVPixelFormat avpriv_find_pix_fmt(const PixelFormatTag *tags, unsigned int fourcc); +enum PixelFormatTagLists { + PIX_FMT_LIST_RAW, + PIX_FMT_LIST_AVI, + PIX_FMT_LIST_MOV, +}; -extern av_export_avcodec const PixelFormatTag avpriv_pix_fmt_bps_avi[]; -extern av_export_avcodec const PixelFormatTag avpriv_pix_fmt_bps_mov[]; +enum AVPixelFormat avpriv_pix_fmt_find(enum PixelFormatTagLists list, + unsigned fourcc); #endif /* AVCODEC_RAW_H */ diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c index b22e36e984..9724cce13f 100644 --- a/libavcodec/rawdec.c +++ b/libavcodec/rawdec.c @@ -76,15 +76,15 @@ static av_cold int raw_init_decoder(AVCodecContext *avctx) if ( avctx->codec_tag == MKTAG('r','a','w',' ') || avctx->codec_tag == MKTAG('N','O','1','6')) - avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov, + avctx->pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_MOV, avctx->bits_per_coded_sample); else if (avctx->codec_tag == MKTAG('W', 'R', 'A', 'W')) - avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, + avctx->pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_AVI, avctx->bits_per_coded_sample); else if (avctx->codec_tag && (avctx->codec_tag & 0xFFFFFF) != MKTAG('B','I','T', 0)) - avctx->pix_fmt = avpriv_find_pix_fmt(ff_raw_pix_fmt_tags, avctx->codec_tag); + avctx->pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_RAW, avctx->codec_tag); else if (avctx->pix_fmt == AV_PIX_FMT_NONE && avctx->bits_per_coded_sample) - avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, + avctx->pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_AVI, avctx->bits_per_coded_sample); desc = av_pix_fmt_desc_get(avctx->pix_fmt); diff --git a/libavcodec/utils.c b/libavcodec/utils.c index a91a54b0dc..4d236ff1cd 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -436,17 +436,6 @@ void ff_color_frame(AVFrame *frame, const int c[4]) } } -enum AVPixelFormat avpriv_find_pix_fmt(const PixelFormatTag *tags, - unsigned int fourcc) -{ - while (tags->pix_fmt >= 0) { - if (tags->fourcc == fourcc) - return tags->pix_fmt; - tags++; - } - return AV_PIX_FMT_NONE; -} - int avpriv_codec_get_cap_skip_frame_fill_param(const AVCodec *codec){ return !!(codec->caps_internal & FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM); } diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index a435ae1807..7e04880b38 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -76,7 +76,7 @@ static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount) return AV_PIX_FMT_0RGB32; } } - return avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), biCompression); // all others + return avpriv_pix_fmt_find(PIX_FMT_LIST_RAW, biCompression); // all others } static enum AVColorRange dshow_color_range(DXVA2_ExtendedFormat *fmt_info) diff --git a/libavformat/avienc.c b/libavformat/avienc.c index 3fbde0be1e..be2493ce55 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -448,7 +448,7 @@ static int avi_write_header(AVFormatContext *s) par->bits_per_coded_sample = 16; avist->pal_offset = avio_tell(pb) + 40; ff_put_bmp_header(pb, par, 0, 0, avi->flipped_raw_rgb); - pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, + pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_AVI, par->bits_per_coded_sample); if ( !par->codec_tag && par->codec_id == AV_CODEC_ID_RAWVIDEO diff --git a/libavformat/demux.c b/libavformat/demux.c index 3f35b3860e..4770e5517f 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -2790,7 +2790,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { if (avctx->codec_id == AV_CODEC_ID_RAWVIDEO && !avctx->codec_tag && !avctx->bits_per_coded_sample) { uint32_t tag= avcodec_pix_fmt_to_codec_tag(avctx->pix_fmt); - if (avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), tag) == avctx->pix_fmt) + if (avpriv_pix_fmt_find(PIX_FMT_LIST_RAW, tag) == avctx->pix_fmt) avctx->codec_tag= tag; } diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 24965c89c2..bc6abcfcaa 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1637,7 +1637,7 @@ static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track) } } - pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov, + pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_MOV, track->par->bits_per_coded_sample); if (tag == MKTAG('r','a','w',' ') && track->par->format != pix_fmt && From d7a75d21635eab4f4a1efea22945933059c2e36f Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Feb 2021 18:25:13 +0100 Subject: [PATCH 29/38] avcodec/ac3tab: Unavpriv ac3_channel_layout_tab It is small (16 B) and therefore the overhead of exporting it more than outweighs the size savings from not having duplicated symbols: When the symbol is no longer avpriv, one saves twice the size of the string containing the symbols name (2x30 byte), two entries in .dynsym (24 bytes each on x64), one entry in the importing libraries .got and .rela.dyn (8 + 24 bytes on x64) and two entries for the symbol version (2 bytes each) and one hash value in the exporting library (4 bytes). (The exact numbers are of course different for other platforms (e.g. when using dlls), but given that the strings saved alone more than outweigh the array size it can be presumed that this is beneficial for all platforms.) Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 12 +++++--- libavcodec/ac3_channel_layout_tab.c | 22 +++++++++++++++ libavcodec/ac3_channel_layout_tab.h | 41 ++++++++++++++++++++++++++++ libavcodec/ac3_parser.c | 2 +- libavcodec/ac3dec.c | 4 +-- libavcodec/ac3enc.h | 1 + libavcodec/ac3tab.c | 14 ---------- libavcodec/ac3tab.h | 4 +-- libavcodec/eac3_data.c | 2 ++ libavformat/Makefile | 2 ++ libavformat/ac3_channel_layout_tab.c | 22 +++++++++++++++ libavformat/hls_sample_encryption.c | 4 ++- libavformat/mov.c | 4 +-- 13 files changed, 107 insertions(+), 27 deletions(-) create mode 100644 libavcodec/ac3_channel_layout_tab.c create mode 100644 libavcodec/ac3_channel_layout_tab.h create mode 100644 libavformat/ac3_channel_layout_tab.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index e048a1c377..68a9075911 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -175,8 +175,10 @@ OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \ psymodel.o mpeg4audio.o kbdwin.o OBJS-$(CONFIG_AAC_MF_ENCODER) += mfenc.o mf_utils.o OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o -OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o kbdwin.o ac3tab.o -OBJS-$(CONFIG_AC3_FIXED_DECODER) += ac3dec_fixed.o ac3dec_data.o ac3.o kbdwin.o ac3tab.o +OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o \ + kbdwin.o ac3tab.o ac3_channel_layout_tab.o +OBJS-$(CONFIG_AC3_FIXED_DECODER) += ac3dec_fixed.o ac3dec_data.o ac3.o \ + kbdwin.o ac3tab.o ac3_channel_layout_tab.o OBJS-$(CONFIG_AC3_ENCODER) += ac3enc_float.o ac3enc.o ac3tab.o \ ac3.o kbdwin.o OBJS-$(CONFIG_AC3_FIXED_ENCODER) += ac3enc_fixed.o ac3enc.o ac3tab.o ac3.o kbdwin.o @@ -992,7 +994,6 @@ OBJS-$(CONFIG_FITS_DEMUXER) += fits.o OBJS-$(CONFIG_LATM_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_MOV_DEMUXER) += ac3tab.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o @@ -1001,6 +1002,8 @@ OBJS-$(CONFIG_TAK_DEMUXER) += tak.o OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o # libavformat dependencies for static builds +STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o +STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o @@ -1087,7 +1090,8 @@ OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o ass.o OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \ mpeg4audio.o -OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o +OBJS-$(CONFIG_AC3_PARSER) += aac_ac3_parser.o ac3tab.o \ + ac3_channel_layout_tab.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AMR_PARSER) += amr_parser.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o diff --git a/libavcodec/ac3_channel_layout_tab.c b/libavcodec/ac3_channel_layout_tab.c new file mode 100644 index 0000000000..4fed46b6e7 --- /dev/null +++ b/libavcodec/ac3_channel_layout_tab.c @@ -0,0 +1,22 @@ +/* + * AC-3 channel layout table + * copyright (c) 2001 Fabrice Bellard + * + * 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 "ac3_channel_layout_tab.h" diff --git a/libavcodec/ac3_channel_layout_tab.h b/libavcodec/ac3_channel_layout_tab.h new file mode 100644 index 0000000000..46fa9ecdfe --- /dev/null +++ b/libavcodec/ac3_channel_layout_tab.h @@ -0,0 +1,41 @@ +/* + * AC-3 channel layout table + * copyright (c) 2001 Fabrice Bellard + * + * 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 + */ + +#ifndef AVCODEC_AC3_CHANNEL_LAYOUT_TAB_H +#define AVCODEC_AC3_CHANNEL_LAYOUT_TAB_H + +#include +#include "libavutil/channel_layout.h" + +/** + * Map audio coding mode (acmod) to channel layout mask. + */ +const uint16_t ff_ac3_channel_layout_tab[8] = { + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_2_1, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_2_2, + AV_CH_LAYOUT_5POINT0 +}; +#endif diff --git a/libavcodec/ac3_parser.c b/libavcodec/ac3_parser.c index 9ed6ede5c3..f3c7d27d59 100644 --- a/libavcodec/ac3_parser.c +++ b/libavcodec/ac3_parser.c @@ -141,7 +141,7 @@ int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr) (hdr->num_blocks * 256); hdr->channels = ff_ac3_channels_tab[hdr->channel_mode] + hdr->lfe_on; } - hdr->channel_layout = avpriv_ac3_channel_layout_tab[hdr->channel_mode]; + hdr->channel_layout = ff_ac3_channel_layout_tab[hdr->channel_mode]; if (hdr->lfe_on) hdr->channel_layout |= AV_CH_LOW_FREQUENCY; diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index c7deb56e1c..ae00373dcb 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -1616,7 +1616,7 @@ dependent_frame: return AVERROR_INVALIDDATA; } avctx->channels = s->out_channels; - avctx->channel_layout = avpriv_ac3_channel_layout_tab[s->output_mode & ~AC3_OUTPUT_LFEON]; + avctx->channel_layout = ff_ac3_channel_layout_tab[s->output_mode & ~AC3_OUTPUT_LFEON]; if (s->output_mode & AC3_OUTPUT_LFEON) avctx->channel_layout |= AV_CH_LOW_FREQUENCY; @@ -1700,7 +1700,7 @@ skip: extended_channel_map[ch] = ch; if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) { - uint64_t ich_layout = avpriv_ac3_channel_layout_tab[s->prev_output_mode & ~AC3_OUTPUT_LFEON]; + uint64_t ich_layout = ff_ac3_channel_layout_tab[s->prev_output_mode & ~AC3_OUTPUT_LFEON]; int channel_map_size = ff_ac3_channels_tab[s->output_mode & ~AC3_OUTPUT_LFEON] + s->lfe_on; uint64_t channel_layout; int extend = 0; diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h index ec9ead8a4e..39a41fe0b0 100644 --- a/libavcodec/ac3enc.h +++ b/libavcodec/ac3enc.h @@ -35,6 +35,7 @@ #include "ac3dsp.h" #include "avcodec.h" #include "fft.h" +#include "internal.h" #include "mathops.h" #include "me_cmp.h" #include "put_bits.h" diff --git a/libavcodec/ac3tab.c b/libavcodec/ac3tab.c index 5c5ea7e27e..766e293a1d 100644 --- a/libavcodec/ac3tab.c +++ b/libavcodec/ac3tab.c @@ -82,20 +82,6 @@ const uint8_t ff_ac3_channels_tab[8] = { 2, 1, 2, 3, 3, 4, 4, 5 }; -/** - * Map audio coding mode (acmod) to channel layout mask. - */ -const uint16_t avpriv_ac3_channel_layout_tab[8] = { - AV_CH_LAYOUT_STEREO, - AV_CH_LAYOUT_MONO, - AV_CH_LAYOUT_STEREO, - AV_CH_LAYOUT_SURROUND, - AV_CH_LAYOUT_2_1, - AV_CH_LAYOUT_4POINT0, - AV_CH_LAYOUT_2_2, - AV_CH_LAYOUT_5POINT0 -}; - /** * Table to remap channels from AC-3 order to SMPTE order. * [channel_mode][lfe][ch] diff --git a/libavcodec/ac3tab.h b/libavcodec/ac3tab.h index ea8e3340c7..bc470204fe 100644 --- a/libavcodec/ac3tab.h +++ b/libavcodec/ac3tab.h @@ -24,13 +24,11 @@ #include -#include "libavutil/internal.h" #include "ac3.h" -#include "internal.h" extern const uint16_t ff_ac3_frame_size_tab[38][3]; extern const uint8_t ff_ac3_channels_tab[8]; -extern av_export_avcodec const uint16_t avpriv_ac3_channel_layout_tab[8]; +extern const uint16_t ff_ac3_channel_layout_tab[8]; extern const uint8_t ff_ac3_dec_channel_map[8][2][6]; extern const int ff_ac3_sample_rate_tab[]; extern const uint16_t ff_ac3_bitrate_tab[19]; diff --git a/libavcodec/eac3_data.c b/libavcodec/eac3_data.c index b159e1682f..2ef0e2053c 100644 --- a/libavcodec/eac3_data.c +++ b/libavcodec/eac3_data.c @@ -24,6 +24,8 @@ * Tables taken directly from the E-AC-3 spec. */ +#include + #include "eac3_data.h" #include "ac3.h" diff --git a/libavformat/Makefile b/libavformat/Makefile index 37281d5ca8..df95c34046 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -681,6 +681,8 @@ OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o # Objects duplicated from other libraries for shared builds SHLIBOBJS += log2_tab.o +SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o +SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o diff --git a/libavformat/ac3_channel_layout_tab.c b/libavformat/ac3_channel_layout_tab.c new file mode 100644 index 0000000000..cba198ccc5 --- /dev/null +++ b/libavformat/ac3_channel_layout_tab.c @@ -0,0 +1,22 @@ +/* + * AC-3 channel layout table + * copyright (c) 2001 Fabrice Bellard + * + * 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 "libavcodec/ac3_channel_layout_tab.h" diff --git a/libavformat/hls_sample_encryption.c b/libavformat/hls_sample_encryption.c index 38795c7fb0..3dbaff717e 100644 --- a/libavformat/hls_sample_encryption.c +++ b/libavformat/hls_sample_encryption.c @@ -26,6 +26,8 @@ * https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/HLS_Sample_Encryption */ +#include "libavutil/channel_layout.h" + #include "hls_sample_encryption.h" #include "libavcodec/adts_header.h" @@ -129,7 +131,7 @@ int ff_hls_senc_parse_audio_setup_info(AVStream *st, HLSAudioSetupInfo *info) st->codecpar->sample_rate = eac3_sample_rate_tab[fscod]; - st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod]; + st->codecpar->channel_layout = ff_ac3_channel_layout_tab[acmod]; if (lfeon) st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY; diff --git a/libavformat/mov.c b/libavformat/mov.c index ad5ab6b491..e401cd39b5 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -813,7 +813,7 @@ static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom) acmod = (ac3info >> 11) & 0x7; lfeon = (ac3info >> 10) & 0x1; st->codecpar->channels = ((int[]){2,1,2,3,3,4,4,5})[acmod] + lfeon; - st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod]; + st->codecpar->channel_layout = ff_ac3_channel_layout_tab[acmod]; if (lfeon) st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY; *ast = bsmod; @@ -846,7 +846,7 @@ static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom) bsmod = (eac3info >> 12) & 0x1f; acmod = (eac3info >> 9) & 0x7; lfeon = (eac3info >> 8) & 0x1; - st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod]; + st->codecpar->channel_layout = ff_ac3_channel_layout_tab[acmod]; if (lfeon) st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY; st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout); From 3afb41655e2afa8f4284f7fc19153cccf62afaa3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Feb 2021 21:16:18 +0100 Subject: [PATCH 30/38] avcodec/dca: Unavpriv dca_sample_rates Said table is 64 bytes long and exported so that it can be used both in libavcodec and libavformat. This commit stops doing so and instead duplicates it for shared builds, because the overhead of exporting the symbol is bigger than 64 bytes. It consists of the length of the name of the symbol (2x24 bytes), two entries in .dynsym (2x24 bytes), two entries for symbol version (2x2 bytes), one hash value in the exporting library (4 bytes) in addition to one entry in the importing library's .got and .rela.dyn (8 + 24 bytes). (The above numbers are for a Linux/GNU/Elf system; the numbers for other platforms may be different.) Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 8 +++++--- libavcodec/dca.c | 7 +------ libavcodec/dca.h | 4 +--- libavcodec/dca_core.c | 2 +- libavcodec/dca_parser.c | 2 +- libavcodec/dca_sample_rate_tab.c | 25 +++++++++++++++++++++++ libavcodec/dca_sample_rate_tab.h | 33 +++++++++++++++++++++++++++++++ libavformat/Makefile | 1 + libavformat/dca_sample_rate_tab.c | 25 +++++++++++++++++++++++ libavformat/spdifenc.c | 2 +- 10 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 libavcodec/dca_sample_rate_tab.c create mode 100644 libavcodec/dca_sample_rate_tab.h create mode 100644 libavformat/dca_sample_rate_tab.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 68a9075911..2500c3ee55 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -276,7 +276,8 @@ OBJS-$(CONFIG_CSCD_DECODER) += cscd.o OBJS-$(CONFIG_CYUV_DECODER) += cyuv.o OBJS-$(CONFIG_DCA_DECODER) += dcadec.o dca.o dcadata.o dcahuff.o \ dca_core.o dca_exss.o dca_xll.o dca_lbr.o \ - dcadsp.o dcadct.o synth_filter.o + dcadsp.o dcadct.o dca_sample_rate_tab.o \ + synth_filter.o OBJS-$(CONFIG_DCA_ENCODER) += dcaenc.o dcadata.o dcahuff.o \ dcaadpcm.o OBJS-$(CONFIG_DDS_DECODER) += dds.o @@ -997,7 +998,6 @@ OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_SPDIF_MUXER) += dca.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o @@ -1006,6 +1006,7 @@ STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o +STLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o # libavfilter dependencies OBJS-$(CONFIG_ELBG_FILTER) += elbg.o @@ -1101,7 +1102,8 @@ OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o OBJS-$(CONFIG_CRI_PARSER) += cri_parser.o -OBJS-$(CONFIG_DCA_PARSER) += dca_parser.o dca_exss.o dca.o +OBJS-$(CONFIG_DCA_PARSER) += dca_parser.o dca_exss.o dca.o \ + dca_sample_rate_tab.o OBJS-$(CONFIG_DIRAC_PARSER) += dirac_parser.o OBJS-$(CONFIG_DNXHD_PARSER) += dnxhd_parser.o dnxhddata.o OBJS-$(CONFIG_DOLBY_E_PARSER) += dolby_e_parser.o dolby_e_parse.o diff --git a/libavcodec/dca.c b/libavcodec/dca.c index b2152524a5..fb359b2ff3 100644 --- a/libavcodec/dca.c +++ b/libavcodec/dca.c @@ -33,11 +33,6 @@ #include "get_bits.h" #include "put_bits.h" -const uint32_t avpriv_dca_sample_rates[16] = { - 0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, - 12000, 24000, 48000, 96000, 192000 -}; - const uint32_t ff_dca_sampling_freqs[16] = { 8000, 16000, 32000, 64000, 128000, 22050, 44100, 88200, 176400, 352800, 12000, 24000, 48000, 96000, 192000, 384000, @@ -112,7 +107,7 @@ int ff_dca_parse_core_frame_header(DCACoreFrameHeader *h, GetBitContext *gb) return DCA_PARSE_ERROR_AMODE; h->sr_code = get_bits(gb, 4); - if (!avpriv_dca_sample_rates[h->sr_code]) + if (!ff_dca_sample_rates[h->sr_code]) return DCA_PARSE_ERROR_SAMPLE_RATE; h->br_code = get_bits(gb, 5); diff --git a/libavcodec/dca.h b/libavcodec/dca.h index e96c589c02..6be975fdfa 100644 --- a/libavcodec/dca.h +++ b/libavcodec/dca.h @@ -32,7 +32,6 @@ #include "libavutil/intreadwrite.h" #include "get_bits.h" -#include "internal.h" #define DCA_CORE_FRAME_HEADER_SIZE 18 @@ -195,8 +194,7 @@ enum DCADownMixType { DCA_DMIX_TYPE_COUNT }; -extern av_export_avcodec const uint32_t avpriv_dca_sample_rates[16]; - +extern const uint32_t ff_dca_sample_rates[16]; extern const uint32_t ff_dca_sampling_freqs[16]; extern const uint8_t ff_dca_freq_ranges[16]; extern const uint8_t ff_dca_bits_per_sample[8]; diff --git a/libavcodec/dca_core.c b/libavcodec/dca_core.c index f0a3c18d62..758e3447a6 100644 --- a/libavcodec/dca_core.c +++ b/libavcodec/dca_core.c @@ -129,7 +129,7 @@ static int parse_frame_header(DCACoreDecoder *s) s->npcmblocks = h.npcmblocks; s->frame_size = h.frame_size; s->audio_mode = h.audio_mode; - s->sample_rate = avpriv_dca_sample_rates[h.sr_code]; + s->sample_rate = ff_dca_sample_rates[h.sr_code]; s->bit_rate = ff_dca_bit_rates[h.br_code]; s->drc_present = h.drc_present; s->ts_present = h.ts_present; diff --git a/libavcodec/dca_parser.c b/libavcodec/dca_parser.c index 8b5c354312..3148397b7d 100644 --- a/libavcodec/dca_parser.c +++ b/libavcodec/dca_parser.c @@ -267,7 +267,7 @@ static int dca_parse_params(DCAParseContext *pc1, const uint8_t *buf, return AVERROR_INVALIDDATA; *duration = h.npcmblocks * DCA_PCMBLOCK_SAMPLES; - *sample_rate = avpriv_dca_sample_rates[h.sr_code]; + *sample_rate = ff_dca_sample_rates[h.sr_code]; if (*profile != FF_PROFILE_UNKNOWN) return 0; diff --git a/libavcodec/dca_sample_rate_tab.c b/libavcodec/dca_sample_rate_tab.c new file mode 100644 index 0000000000..16ee04b1d2 --- /dev/null +++ b/libavcodec/dca_sample_rate_tab.c @@ -0,0 +1,25 @@ +/* + * DCA sample rates + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larsson + * Copyright (C) 2007 Konstantin Shishkov + * + * 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 "dca_sample_rate_tab.h" diff --git a/libavcodec/dca_sample_rate_tab.h b/libavcodec/dca_sample_rate_tab.h new file mode 100644 index 0000000000..93d9a13663 --- /dev/null +++ b/libavcodec/dca_sample_rate_tab.h @@ -0,0 +1,33 @@ +/* + * DCA sample rates + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larssonb + * Copyright (C) 2007 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_DCA_SAMPLE_RATE_TAB_H +#define AVCODEC_DCA_SAMPLE_RATE_TAB_H +#include + +const uint32_t ff_dca_sample_rates[16] = { + 0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, + 12000, 24000, 48000, 96000, 192000 +}; +#endif diff --git a/libavformat/Makefile b/libavformat/Makefile index df95c34046..82e7fd3dc7 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -685,6 +685,7 @@ SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o +SHLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o # libavdevice dependencies OBJS-$(CONFIG_IEC61883_INDEV) += dv.o diff --git a/libavformat/dca_sample_rate_tab.c b/libavformat/dca_sample_rate_tab.c new file mode 100644 index 0000000000..ed2380b0cd --- /dev/null +++ b/libavformat/dca_sample_rate_tab.c @@ -0,0 +1,25 @@ +/* + * DCA sample rates + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larsson + * Copyright (C) 2007 Konstantin Shishkov + * + * 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 "libavcodec/dca_sample_rate_tab.h" diff --git a/libavformat/spdifenc.c b/libavformat/spdifenc.c index e8f54bff4b..3be89328df 100644 --- a/libavformat/spdifenc.c +++ b/libavformat/spdifenc.c @@ -263,7 +263,7 @@ static int spdif_header_dts(AVFormatContext *s, AVPacket *pkt) case DCA_SYNCWORD_CORE_BE: blocks = (AV_RB16(pkt->data + 4) >> 2) & 0x7f; core_size = ((AV_RB24(pkt->data + 5) >> 4) & 0x3fff) + 1; - sample_rate = avpriv_dca_sample_rates[(pkt->data[8] >> 2) & 0x0f]; + sample_rate = ff_dca_sample_rates[(pkt->data[8] >> 2) & 0x0f]; break; case DCA_SYNCWORD_CORE_LE: blocks = (AV_RL16(pkt->data + 4) >> 2) & 0x7f; From 1d333c154718f3851b3af2d86663451d353e3685 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 10 Feb 2021 01:19:44 +0100 Subject: [PATCH 31/38] avcodec/jpegtables: Unavpriv MJPEG-tables There are seven MJPEG-tables, five small (1x12, 4x17) and two not small (2x162). These are all avpriv, despite this not being worthwhile due to the overhead of exporting a symbol: The total overhead for each symbol consists of two entries in .dynsym (24B each), one entry in the importing library's .rela.dyn (24B) and one in .got (8B) as well as 2x2B for symbol versions and 4B for symbol hashes in the exporting library; in addition to that, the name of the symbol is included in both exporting and importing libraries, using 2x210 bytes in this case. (The above numbers are for a x64 Elf/Linux/GNU system. Other platforms will give different numbers.) Signed-off-by: Andreas Rheinhardt --- configure | 3 +- libavcodec/Makefile | 3 +- libavcodec/g2meet.c | 16 +++--- libavcodec/jpegtables.c | 66 +---------------------- libavcodec/jpegtables.h | 16 +++--- libavcodec/jpegtabs.h | 92 +++++++++++++++++++++++++++++++++ libavcodec/ljpegenc.c | 8 +-- libavcodec/mjpeg2jpeg_bsf.c | 12 ++--- libavcodec/mjpegdec.c | 24 ++++----- libavcodec/mjpegenc.c | 16 +++--- libavcodec/mjpegenc_common.c | 16 +++--- libavcodec/mss4.c | 8 +-- libavcodec/vaapi_encode_mjpeg.c | 16 +++--- libavformat/Makefile | 3 +- libavformat/jpegtables.c | 24 +++++++++ libavformat/rtpdec_jpeg.c | 16 +++--- libavformat/rtpenc_jpeg.c | 16 +++--- 17 files changed, 203 insertions(+), 152 deletions(-) create mode 100644 libavcodec/jpegtabs.h create mode 100644 libavformat/jpegtables.c diff --git a/configure b/configure index 50aa0d596d..f04288cf8d 100755 --- a/configure +++ b/configure @@ -3451,9 +3451,8 @@ ogv_muxer_select="ogg_muxer" opus_muxer_select="ogg_muxer" psp_muxer_select="mov_muxer" rtp_demuxer_select="sdp_demuxer" -rtp_muxer_select="jpegtables" rtp_mpegts_muxer_select="mpegts_muxer rtp_muxer" -rtpdec_select="asf_demuxer jpegtables mov_demuxer mpegts_demuxer rm_demuxer rtp_protocol srtp" +rtpdec_select="asf_demuxer mov_demuxer mpegts_demuxer rm_demuxer rtp_protocol srtp" rtsp_demuxer_select="http_protocol rtpdec" rtsp_muxer_select="rtp_muxer http_protocol rtp_protocol rtpenc_chain" sap_demuxer_select="sdp_demuxer" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2500c3ee55..4afc290710 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1005,7 +1005,8 @@ OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o -STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o +STLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o +STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o jpegtables.o STLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o # libavfilter dependencies diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index c9e8d11ab8..4c53838af5 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -164,20 +164,20 @@ static av_cold int jpg_init(AVCodecContext *avctx, JPGContext *c) { int ret; - ret = ff_mjpeg_build_vlc(&c->dc_vlc[0], avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc, 0, avctx); + ret = ff_mjpeg_build_vlc(&c->dc_vlc[0], ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc, 0, avctx); if (ret) return ret; - ret = ff_mjpeg_build_vlc(&c->dc_vlc[1], avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc, 0, avctx); + ret = ff_mjpeg_build_vlc(&c->dc_vlc[1], ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc, 0, avctx); if (ret) return ret; - ret = ff_mjpeg_build_vlc(&c->ac_vlc[0], avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance, 1, avctx); + ret = ff_mjpeg_build_vlc(&c->ac_vlc[0], ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance, 1, avctx); if (ret) return ret; - ret = ff_mjpeg_build_vlc(&c->ac_vlc[1], avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance, 1, avctx); + ret = ff_mjpeg_build_vlc(&c->ac_vlc[1], ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance, 1, avctx); if (ret) return ret; diff --git a/libavcodec/jpegtables.c b/libavcodec/jpegtables.c index ef3f8dee20..e453fcf90d 100644 --- a/libavcodec/jpegtables.c +++ b/libavcodec/jpegtables.c @@ -30,8 +30,7 @@ * MJPEG encoder and decoder. */ -#include "jpegtables.h" - +#include "jpegtabs.h" #if 0 /* These are the sample quantization tables given in JPEG spec section K.1. @@ -59,66 +58,3 @@ static const unsigned char std_chrominance_quant_tbl[64] = { 99, 99, 99, 99, 99, 99, 99, 99 }; #endif - -/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ -/* IMPORTANT: these are only valid for 8-bit data precision! */ -const uint8_t avpriv_mjpeg_bits_dc_luminance[17] = -{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; -const uint8_t avpriv_mjpeg_val_dc[12] = -{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; - -const uint8_t avpriv_mjpeg_bits_dc_chrominance[17] = -{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; - -const uint8_t avpriv_mjpeg_bits_ac_luminance[17] = -{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; -const uint8_t avpriv_mjpeg_val_ac_luminance[] = -{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, - 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, - 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, - 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, - 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa -}; - -const uint8_t avpriv_mjpeg_bits_ac_chrominance[17] = -{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; - -const uint8_t avpriv_mjpeg_val_ac_chrominance[] = -{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, - 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, - 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, - 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, - 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, - 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, - 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, - 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, - 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, - 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa -}; diff --git a/libavcodec/jpegtables.h b/libavcodec/jpegtables.h index 0907280445..49b5ecdeb0 100644 --- a/libavcodec/jpegtables.h +++ b/libavcodec/jpegtables.h @@ -23,17 +23,15 @@ #include -#include "internal.h" +extern const uint8_t ff_mjpeg_bits_dc_luminance[]; +extern const uint8_t ff_mjpeg_val_dc[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_dc_luminance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_val_dc[]; +extern const uint8_t ff_mjpeg_bits_dc_chrominance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_dc_chrominance[]; +extern const uint8_t ff_mjpeg_bits_ac_luminance[]; +extern const uint8_t ff_mjpeg_val_ac_luminance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_ac_luminance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_val_ac_luminance[]; - -extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_ac_chrominance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_val_ac_chrominance[]; +extern const uint8_t ff_mjpeg_bits_ac_chrominance[]; +extern const uint8_t ff_mjpeg_val_ac_chrominance[]; #endif /* AVCODEC_JPEGTABLES_H */ diff --git a/libavcodec/jpegtabs.h b/libavcodec/jpegtabs.h new file mode 100644 index 0000000000..7106f66df0 --- /dev/null +++ b/libavcodec/jpegtabs.h @@ -0,0 +1,92 @@ +/* + * MJPEG tables + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-2004 Michael Niedermayer + * + * 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 + */ + +#ifndef AVCODEC_JPEGTABS_H +#define AVCODEC_JPEGTABS_H + +#include +#include "jpegtables.h" + +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +const uint8_t ff_mjpeg_bits_dc_luminance[17] = +{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; +const uint8_t ff_mjpeg_val_dc[12] = +{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + +const uint8_t ff_mjpeg_bits_dc_chrominance[17] = +{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + +const uint8_t ff_mjpeg_bits_ac_luminance[17] = +{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; +const uint8_t ff_mjpeg_val_ac_luminance[] = +{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; + +const uint8_t ff_mjpeg_bits_ac_chrominance[17] = +{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + +const uint8_t ff_mjpeg_val_ac_chrominance[] = +{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; +#endif diff --git a/libavcodec/ljpegenc.c b/libavcodec/ljpegenc.c index 968ba1fb60..ecdedeb6a3 100644 --- a/libavcodec/ljpegenc.c +++ b/libavcodec/ljpegenc.c @@ -293,12 +293,12 @@ static av_cold int ljpeg_encode_init(AVCodecContext *avctx) ff_mjpeg_build_huffman_codes(s->huff_size_dc_luminance, s->huff_code_dc_luminance, - avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); + ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc); ff_mjpeg_build_huffman_codes(s->huff_size_dc_chrominance, s->huff_code_dc_chrominance, - avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); + ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc); return 0; } diff --git a/libavcodec/mjpeg2jpeg_bsf.c b/libavcodec/mjpeg2jpeg_bsf.c index b30f391bf9..2a972a7c37 100644 --- a/libavcodec/mjpeg2jpeg_bsf.c +++ b/libavcodec/mjpeg2jpeg_bsf.c @@ -65,15 +65,15 @@ static uint8_t *append(uint8_t *buf, const uint8_t *src, int size) static uint8_t *append_dht_segment(uint8_t *buf) { buf = append(buf, dht_segment_head, sizeof(dht_segment_head)); - buf = append(buf, avpriv_mjpeg_bits_dc_luminance + 1, 16); + buf = append(buf, ff_mjpeg_bits_dc_luminance + 1, 16); buf = append(buf, dht_segment_frag, sizeof(dht_segment_frag)); - buf = append(buf, avpriv_mjpeg_val_dc, 12); + buf = append(buf, ff_mjpeg_val_dc, 12); *(buf++) = 0x10; - buf = append(buf, avpriv_mjpeg_bits_ac_luminance + 1, 16); - buf = append(buf, avpriv_mjpeg_val_ac_luminance, 162); + buf = append(buf, ff_mjpeg_bits_ac_luminance + 1, 16); + buf = append(buf, ff_mjpeg_val_ac_luminance, 162); *(buf++) = 0x11; - buf = append(buf, avpriv_mjpeg_bits_ac_chrominance + 1, 16); - buf = append(buf, avpriv_mjpeg_val_ac_chrominance, 162); + buf = append(buf, ff_mjpeg_bits_ac_chrominance + 1, 16); + buf = append(buf, ff_mjpeg_val_ac_chrominance, 162); return buf; } diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 0dbbc14bae..a735d2337d 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -61,18 +61,18 @@ static int init_default_huffman_tables(MJpegDecodeContext *s) const uint8_t *values; int length; } ht[] = { - { 0, 0, avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc, 12 }, - { 0, 1, avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc, 12 }, - { 1, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance, 162 }, - { 1, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance, 162 }, - { 2, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance, 162 }, - { 2, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance, 162 }, + { 0, 0, ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc, 12 }, + { 0, 1, ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc, 12 }, + { 1, 0, ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance, 162 }, + { 1, 1, ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance, 162 }, + { 2, 0, ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance, 162 }, + { 2, 1, ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance, 162 }, }; int i, ret; diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 0ade66bc5f..30cbbddb59 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -288,20 +288,20 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) // they are needed at least right now for some processes like trellis. ff_mjpeg_build_huffman_codes(m->huff_size_dc_luminance, m->huff_code_dc_luminance, - avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); + ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc); ff_mjpeg_build_huffman_codes(m->huff_size_dc_chrominance, m->huff_code_dc_chrominance, - avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); + ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc); ff_mjpeg_build_huffman_codes(m->huff_size_ac_luminance, m->huff_code_ac_luminance, - avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance); + ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance); ff_mjpeg_build_huffman_codes(m->huff_size_ac_chrominance, m->huff_code_ac_chrominance, - avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance); + ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance); init_uni_ac_vlc(m->huff_size_ac_luminance, m->uni_ac_vlc_len); init_uni_ac_vlc(m->huff_size_ac_chrominance, m->uni_chroma_ac_vlc_len); diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index c1b842d547..368e87128c 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -121,15 +121,15 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, size += put_huffman_table(p, 1, 1, s->mjpeg_ctx->bits_ac_chrominance, s->mjpeg_ctx->val_ac_chrominance); } else { - size += put_huffman_table(p, 0, 0, avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); - size += put_huffman_table(p, 0, 1, avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); + size += put_huffman_table(p, 0, 0, ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc); + size += put_huffman_table(p, 0, 1, ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc); - size += put_huffman_table(p, 1, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance); - size += put_huffman_table(p, 1, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance); + size += put_huffman_table(p, 1, 0, ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance); + size += put_huffman_table(p, 1, 1, ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance); } AV_WB16(ptr, size); } diff --git a/libavcodec/mss4.c b/libavcodec/mss4.c index 6c44c76c50..216df2852d 100644 --- a/libavcodec/mss4.c +++ b/libavcodec/mss4.c @@ -124,10 +124,10 @@ static av_cold void mss4_init_vlcs(void) for (unsigned i = 0, offset = 0; i < 2; i++) { mss4_init_vlc(&dc_vlc[i], &offset, mss4_dc_vlc_lens[i], NULL); mss4_init_vlc(&ac_vlc[i], &offset, - i ? avpriv_mjpeg_bits_ac_chrominance + 1 - : avpriv_mjpeg_bits_ac_luminance + 1, - i ? avpriv_mjpeg_val_ac_chrominance - : avpriv_mjpeg_val_ac_luminance); + i ? ff_mjpeg_bits_ac_chrominance + 1 + : ff_mjpeg_bits_ac_luminance + 1, + i ? ff_mjpeg_val_ac_chrominance + : ff_mjpeg_val_ac_luminance); mss4_init_vlc(&vec_entry_vlc[i], &offset, mss4_vec_entry_vlc_lens[i], mss4_vec_entry_vlc_syms[i]); } diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c index d35f416ad7..6206b23e5f 100644 --- a/libavcodec/vaapi_encode_mjpeg.c +++ b/libavcodec/vaapi_encode_mjpeg.c @@ -327,20 +327,20 @@ static int vaapi_encode_mjpeg_init_picture_params(AVCodecContext *avctx, switch (t) { case 0: - lengths = avpriv_mjpeg_bits_dc_luminance + 1; - values = avpriv_mjpeg_val_dc; + lengths = ff_mjpeg_bits_dc_luminance + 1; + values = ff_mjpeg_val_dc; break; case 1: - lengths = avpriv_mjpeg_bits_ac_luminance + 1; - values = avpriv_mjpeg_val_ac_luminance; + lengths = ff_mjpeg_bits_ac_luminance + 1; + values = ff_mjpeg_val_ac_luminance; break; case 2: - lengths = avpriv_mjpeg_bits_dc_chrominance + 1; - values = avpriv_mjpeg_val_dc; + lengths = ff_mjpeg_bits_dc_chrominance + 1; + values = ff_mjpeg_val_dc; break; case 3: - lengths = avpriv_mjpeg_bits_ac_chrominance + 1; - values = avpriv_mjpeg_val_ac_chrominance; + lengths = ff_mjpeg_bits_ac_chrominance + 1; + values = ff_mjpeg_val_ac_chrominance; break; } diff --git a/libavformat/Makefile b/libavformat/Makefile index 82e7fd3dc7..f5d6b8fecf 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -684,7 +684,8 @@ SHLIBOBJS += log2_tab.o SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o -SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o +SHLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o +SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o jpegtables.o SHLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o # libavdevice dependencies diff --git a/libavformat/jpegtables.c b/libavformat/jpegtables.c new file mode 100644 index 0000000000..57eae9f9a6 --- /dev/null +++ b/libavformat/jpegtables.c @@ -0,0 +1,24 @@ +/* + * MJPEG tables + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-2004 Michael Niedermayer + * + * 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 "libavcodec/jpegtabs.h" diff --git a/libavformat/rtpdec_jpeg.c b/libavformat/rtpdec_jpeg.c index b32d074136..81036247c1 100644 --- a/libavformat/rtpdec_jpeg.c +++ b/libavformat/rtpdec_jpeg.c @@ -144,14 +144,14 @@ static int jpeg_create_header(uint8_t *buf, int size, uint32_t type, uint32_t w, bytestream2_put_be16(&pbc, 0); dht_size = 2; - dht_size += jpeg_create_huffman_table(&pbc, 0, 0,avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); - dht_size += jpeg_create_huffman_table(&pbc, 0, 1, avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); - dht_size += jpeg_create_huffman_table(&pbc, 1, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance); - dht_size += jpeg_create_huffman_table(&pbc, 1, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance); + dht_size += jpeg_create_huffman_table(&pbc, 0, 0,ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc); + dht_size += jpeg_create_huffman_table(&pbc, 0, 1, ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc); + dht_size += jpeg_create_huffman_table(&pbc, 1, 0, ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance); + dht_size += jpeg_create_huffman_table(&pbc, 1, 1, ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance); AV_WB16(dht_size_ptr, dht_size); /* SOF0 */ diff --git a/libavformat/rtpenc_jpeg.c b/libavformat/rtpenc_jpeg.c index 38eb2e68eb..91116832da 100644 --- a/libavformat/rtpenc_jpeg.c +++ b/libavformat/rtpenc_jpeg.c @@ -101,8 +101,8 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) switch (buf[i + 1]) { case 0x00: if ( dht_size >= 29 - && !memcmp(buf + i + 2, avpriv_mjpeg_bits_dc_luminance + 1, 16) - && !memcmp(buf + i + 18, avpriv_mjpeg_val_dc, 12)) { + && !memcmp(buf + i + 2, ff_mjpeg_bits_dc_luminance + 1, 16) + && !memcmp(buf + i + 18, ff_mjpeg_val_dc, 12)) { default_huffman_tables |= 1; i += 29; dht_size -= 29; @@ -113,8 +113,8 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) break; case 0x01: if ( dht_size >= 29 - && !memcmp(buf + i + 2, avpriv_mjpeg_bits_dc_chrominance + 1, 16) - && !memcmp(buf + i + 18, avpriv_mjpeg_val_dc, 12)) { + && !memcmp(buf + i + 2, ff_mjpeg_bits_dc_chrominance + 1, 16) + && !memcmp(buf + i + 18, ff_mjpeg_val_dc, 12)) { default_huffman_tables |= 1 << 1; i += 29; dht_size -= 29; @@ -125,8 +125,8 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) break; case 0x10: if ( dht_size >= 179 - && !memcmp(buf + i + 2, avpriv_mjpeg_bits_ac_luminance + 1, 16) - && !memcmp(buf + i + 18, avpriv_mjpeg_val_ac_luminance, 162)) { + && !memcmp(buf + i + 2, ff_mjpeg_bits_ac_luminance + 1, 16) + && !memcmp(buf + i + 18, ff_mjpeg_val_ac_luminance, 162)) { default_huffman_tables |= 1 << 2; i += 179; dht_size -= 179; @@ -137,8 +137,8 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) break; case 0x11: if ( dht_size >= 179 - && !memcmp(buf + i + 2, avpriv_mjpeg_bits_ac_chrominance + 1, 16) - && !memcmp(buf + i + 18, avpriv_mjpeg_val_ac_chrominance, 162)) { + && !memcmp(buf + i + 2, ff_mjpeg_bits_ac_chrominance + 1, 16) + && !memcmp(buf + i + 18, ff_mjpeg_val_ac_chrominance, 162)) { default_huffman_tables |= 1 << 3; i += 179; dht_size -= 179; From d82c91ba2f889bc5e0ee7c976219f91e62dc9f8b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 14 Dec 2021 11:19:08 +0100 Subject: [PATCH 32/38] configure, avcodec/Makefile: Add new mpeg4audio CONFIG_EXTRA group This group is mainly for the users of *_mpeg4audio_get_config2(); it is not for those who only use avpriv_mpeg4audio_sample_rates. This is in preparation for splitting the latter into a file of its own; if there were no CONFIG_EXTRA group for *_mpeg4audio_get_config2() users, one would have to add a dependency to the new file for all these users on top of the existing dependency on mpeg4audio.o. Adding a new CONFIG_EXTRA group only takes effect after a reconfigure; so in order to force a reconfigure some unnecessary headers from libavdevice/alldevices.c have been removed. Signed-off-by: Andreas Rheinhardt --- configure | 23 +++++++++++++---------- libavcodec/Makefile | 23 +++++++++-------------- libavdevice/alldevices.c | 2 -- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/configure b/configure index f04288cf8d..729e9b5ac7 100755 --- a/configure +++ b/configure @@ -2476,6 +2476,7 @@ CONFIG_EXTRA=" mpegaudio mpegaudiodsp mpegaudioheader + mpeg4audio mpegvideo mpegvideoenc mss34dsp @@ -2719,6 +2720,7 @@ h264dsp_select="startcode" hevcparse_select="atsc_a53 golomb" frame_thread_encoder_deps="encoders threads" intrax8_select="blockdsp idctdsp" +iso_media_select="mpeg4audio" mdct_select="fft" mdct15_select="fft" me_cmp_select="fdctdsp idctdsp pixblockdsp" @@ -2731,8 +2733,8 @@ vc1dsp_select="h264chroma qpeldsp startcode" rdft_select="fft" # decoders / encoders -aac_decoder_select="adts_header mdct15 mdct sinewin" -aac_fixed_decoder_select="adts_header mdct" +aac_decoder_select="adts_header mdct15 mdct mpeg4audio sinewin" +aac_fixed_decoder_select="adts_header mdct mpeg4audio" aac_encoder_select="audio_frame_queue iirfilter lpc mdct sinewin" aac_latm_decoder_select="aac_decoder aac_latm_parser" ac3_decoder_select="ac3_parser ac3dsp bswapdsp fmtconvert mdct" @@ -2744,7 +2746,7 @@ adpcm_g722_decoder_select="g722dsp" adpcm_g722_encoder_select="g722dsp" aic_decoder_select="golomb idctdsp" alac_encoder_select="lpc" -als_decoder_select="bswapdsp" +als_decoder_select="bswapdsp mpeg4audio" amrnb_decoder_select="lsp" amrwb_decoder_select="lsp" amv_decoder_select="sp5x_decoder exif" @@ -2864,8 +2866,8 @@ mp3_decoder_select="mpegaudio" mp3adu_decoder_select="mpegaudio" mp3adufloat_decoder_select="mpegaudio" mp3float_decoder_select="mpegaudio" -mp3on4_decoder_select="mpegaudio" -mp3on4float_decoder_select="mpegaudio" +mp3on4_decoder_select="mpegaudio mpeg4audio" +mp3on4float_decoder_select="mpegaudio mpeg4audio" mpc7_decoder_select="bswapdsp mpegaudiodsp" mpc8_decoder_select="mpegaudiodsp" mpegvideo_decoder_select="mpegvideo" @@ -3242,7 +3244,7 @@ wmv3_crystalhd_decoder_select="crystalhd" av1_qsv_decoder_select="qsvdec" # parsers -aac_parser_select="adts_header" +aac_parser_select="adts_header mpeg4audio" av1_parser_select="cbs_av1" h264_parser_select="atsc_a53 golomb h264dsp h264parse" hevc_parser_select="hevcparse" @@ -3252,7 +3254,7 @@ mpeg4video_parser_select="h263dsp mpegvideo qpeldsp" vc1_parser_select="vc1dsp" # bitstream_filters -aac_adtstoasc_bsf_select="adts_header" +aac_adtstoasc_bsf_select="adts_header mpeg4audio" av1_frame_merge_bsf_select="cbs_av1" av1_frame_split_bsf_select="cbs_av1" av1_metadata_bsf_select="cbs_av1" @@ -3387,6 +3389,7 @@ videotoolbox_encoder_deps="videotoolbox VTCompressionSessionPrepareToEncodeFrame # demuxers / muxers ac3_demuxer_select="ac3_parser" act_demuxer_select="riffdec" +adts_muxer_select="mpeg4audio" aiff_muxer_select="iso_media" asf_demuxer_select="riffdec" asf_o_demuxer_select="riffdec" @@ -3422,11 +3425,11 @@ imf_demuxer_select="mxf_demuxer" ipod_muxer_select="mov_muxer" ismv_muxer_select="mov_muxer" ivf_muxer_select="av1_metadata_bsf vp9_superframe_bsf" -latm_muxer_select="aac_adtstoasc_bsf" +latm_muxer_select="aac_adtstoasc_bsf mpeg4audio" matroska_audio_muxer_select="matroska_muxer" matroska_demuxer_select="riffdec" matroska_demuxer_suggest="bzlib lzo zlib" -matroska_muxer_select="riffenc vp9_superframe_bsf aac_adtstoasc_bsf" +matroska_muxer_select="mpeg4audio riffenc vp9_superframe_bsf aac_adtstoasc_bsf" mlp_demuxer_select="mlp_parser" mmf_muxer_select="riffenc" mov_demuxer_select="iso_media riffdec" @@ -3473,7 +3476,7 @@ w64_muxer_select="wav_muxer" wav_demuxer_select="riffdec" wav_muxer_select="riffenc" webm_chunk_muxer_select="webm_muxer" -webm_muxer_select="riffenc" +webm_muxer_select="mpeg4audio riffenc" webm_dash_manifest_demuxer_select="matroska_demuxer" wtv_demuxer_select="mpegts_demuxer riffdec" wtv_muxer_select="mpegts_muxer riffenc" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 4afc290710..6b141d3706 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -124,6 +124,7 @@ OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ mpegaudiodsp_fixed.o \ mpegaudiodsp_float.o OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiodata.o +OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o rl.o \ mpegvideo_motion.o mpegutils.o \ mpegvideodata.o mpegpicture.o @@ -161,10 +162,10 @@ OBJS-$(CONFIG_ZERO12V_DECODER) += 012v.o OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o aacsbr.o aacps_common.o aacps_float.o \ - mpeg4audio.o kbdwin.o \ + kbdwin.o \ sbrdsp.o aacpsdsp_float.o cbrt_data.o OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aactab.o aacsbr_fixed.o aacps_common.o aacps_fixed.o \ - mpeg4audio.o kbdwin.o \ + kbdwin.o \ sbrdsp_fixed.o aacpsdsp_fixed.o cbrt_data_fixed.o OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \ aacpsy.o aactab.o \ @@ -190,7 +191,7 @@ OBJS-$(CONFIG_ALAC_DECODER) += alac.o alac_data.o alacdsp.o OBJS-$(CONFIG_ALAC_ENCODER) += alacenc.o alac_data.o OBJS-$(CONFIG_ALIAS_PIX_DECODER) += aliaspixdec.o OBJS-$(CONFIG_ALIAS_PIX_ENCODER) += aliaspixenc.o -OBJS-$(CONFIG_ALS_DECODER) += alsdec.o bgmc.o mlz.o mpeg4audio.o +OBJS-$(CONFIG_ALS_DECODER) += alsdec.o bgmc.o mlz.o OBJS-$(CONFIG_AMRNB_DECODER) += amrnbdec.o celp_filters.o \ celp_math.o acelp_filters.o \ acelp_vectors.o \ @@ -481,8 +482,8 @@ OBJS-$(CONFIG_MP3_MF_ENCODER) += mfenc.o mf_utils.o OBJS-$(CONFIG_MP3ADU_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP3ADUFLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MP3FLOAT_DECODER) += mpegaudiodec_float.o -OBJS-$(CONFIG_MP3ON4_DECODER) += mpegaudiodec_fixed.o mpeg4audio.o -OBJS-$(CONFIG_MP3ON4FLOAT_DECODER) += mpegaudiodec_float.o mpeg4audio.o +OBJS-$(CONFIG_MP3ON4_DECODER) += mpegaudiodec_fixed.o +OBJS-$(CONFIG_MP3ON4FLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MPC7_DECODER) += mpc7.o mpc.o OBJS-$(CONFIG_MPC8_DECODER) += mpc8.o mpc.o OBJS-$(CONFIG_MPEGVIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o @@ -988,18 +989,13 @@ OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec.o SHLIBOBJS += log2_tab.o reverse.o # General libavformat dependencies -OBJS-$(CONFIG_ISO_MEDIA) += mpeg4audio.o mpegaudiodata.o +OBJS-$(CONFIG_ISO_MEDIA) += mpegaudiodata.o -OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o OBJS-$(CONFIG_FITS_DEMUXER) += fits.o -OBJS-$(CONFIG_LATM_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o -OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o # libavformat dependencies for static builds STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o @@ -1090,8 +1086,7 @@ OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o ass.o # parsers OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o -OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \ - mpeg4audio.o +OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o OBJS-$(CONFIG_AC3_PARSER) += aac_ac3_parser.o ac3tab.o \ ac3_channel_layout_tab.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o @@ -1151,7 +1146,7 @@ OBJS-$(CONFIG_XBM_PARSER) += xbm_parser.o OBJS-$(CONFIG_XMA_PARSER) += xma_parser.o # bitstream filters -OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o mpeg4audio.o +OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o OBJS-$(CONFIG_AV1_METADATA_BSF) += av1_metadata_bsf.o OBJS-$(CONFIG_AV1_FRAME_MERGE_BSF) += av1_frame_merge_bsf.o OBJS-$(CONFIG_AV1_FRAME_SPLIT_BSF) += av1_frame_split_bsf.o diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index fbbe187a51..22323a0a44 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -18,8 +18,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "config.h" -#include "libavutil/thread.h" #include "libavformat/internal.h" #include "avdevice.h" From 49bf94536f059340eacd5430592e4216b29d0d20 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 10 Feb 2021 19:37:37 +0100 Subject: [PATCH 33/38] avcodec/mpeg4audio: Unavpriv and deduplicate mpeg4audio_sample_rates avpriv_mpeg4audio_sample_rates has a size of 64B and it is currently avpriv; a clone of it exists in aacenctab.h and from there it is inlined in aacenc.c (which also uses the avpriv version) and in the FLV muxer. This means that despite it being avpriv both libavformat as well as libavcodec have copies already. This situation is clearly suboptimal. Given the overhead of exporting symbols (for x64 Elf/Linux/GNU: 2x2B version, 2x24B .dynsym, 24B .rela.dyn, 8B .got, 4B hash + twice the size of the name (here 31B)) the object is unavprived, i.e. duplicated into libavformat when creating a shared build; but the duplicates in the AAC encoder and FLV muxer are removed. This involves splitting of the sample rate table into a file of its own; this allowed to break some spurious dependencies (e.g. both the AAC encoder as well as the Matroska demuxer actually don't need the mpeg4audio_get_config stuff). Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 14 +++++++------ libavcodec/aacenc.c | 4 ++-- libavcodec/aacenctab.h | 7 ------- libavcodec/adts_header.c | 4 ++-- libavcodec/mpeg4audio.c | 9 +------- libavcodec/mpeg4audio.h | 3 +-- libavcodec/mpeg4audio_sample_rates.c | 23 ++++++++++++++++++++ libavcodec/mpeg4audio_sample_rates.h | 30 +++++++++++++++++++++++++++ libavformat/Makefile | 5 ++++- libavformat/flvenc.c | 4 ++-- libavformat/matroskadec.c | 4 ++-- libavformat/mpeg4audio_sample_rates.c | 23 ++++++++++++++++++++ libavformat/sdp.c | 2 +- 13 files changed, 99 insertions(+), 33 deletions(-) create mode 100644 libavcodec/mpeg4audio_sample_rates.c create mode 100644 libavcodec/mpeg4audio_sample_rates.h create mode 100644 libavformat/mpeg4audio_sample_rates.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 6b141d3706..63b4952eaf 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -60,7 +60,7 @@ OBJS = ac3_parser.o \ # subsystems OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o OBJS-$(CONFIG_AC3DSP) += ac3dsp.o ac3.o ac3tab.o -OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio.o +OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio_sample_rates.o OBJS-$(CONFIG_AMF) += amfenc.o OBJS-$(CONFIG_AUDIO_FRAME_QUEUE) += audio_frame_queue.o OBJS-$(CONFIG_ATSC_A53) += atsc_a53.o @@ -124,7 +124,7 @@ OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ mpegaudiodsp_fixed.o \ mpegaudiodsp_float.o OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiodata.o -OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o +OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o mpeg4audio_sample_rates.o OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o rl.o \ mpegvideo_motion.o mpegutils.o \ mpegvideodata.o mpegpicture.o @@ -173,7 +173,8 @@ OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \ aacenc_tns.o \ aacenc_ltp.o \ aacenc_pred.o \ - psymodel.o mpeg4audio.o kbdwin.o + psymodel.o kbdwin.o \ + mpeg4audio_sample_rates.o OBJS-$(CONFIG_AAC_MF_ENCODER) += mfenc.o mf_utils.o OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o \ @@ -992,17 +993,18 @@ SHLIBOBJS += log2_tab.o reverse.o OBJS-$(CONFIG_ISO_MEDIA) += mpegaudiodata.o OBJS-$(CONFIG_FITS_DEMUXER) += fits.o -OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o -OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o # libavformat dependencies for static builds +STLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o +STLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o STLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o -STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o jpegtables.o +STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o jpegtables.o \ + mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o # libavfilter dependencies diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index e462566078..a1004c3e98 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -998,7 +998,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) /* Samplerate */ for (i = 0; i < 16; i++) - if (avctx->sample_rate == avpriv_mpeg4audio_sample_rates[i]) + if (avctx->sample_rate == ff_mpeg4audio_sample_rates[i]) break; s->samplerate_index = i; ERROR_IF(s->samplerate_index == 16 || @@ -1143,7 +1143,7 @@ const AVCodec ff_aac_encoder = { .encode2 = aac_encode_frame, .close = aac_encode_end, .defaults = aac_encode_defaults, - .supported_samplerates = mpeg4audio_sample_rates, + .supported_samplerates = ff_mpeg4audio_sample_rates, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, diff --git a/libavcodec/aacenctab.h b/libavcodec/aacenctab.h index f54dd16bed..33cb7ae95b 100644 --- a/libavcodec/aacenctab.h +++ b/libavcodec/aacenctab.h @@ -81,13 +81,6 @@ static const uint8_t aac_chan_maps[AAC_MAX_CHANNELS][AAC_MAX_CHANNELS] = { { 2, 0, 1, 6, 7, 4, 5, 3 }, }; -/* duplicated from avpriv_mpeg4audio_sample_rates to avoid shared build - * failures */ -static const int mpeg4audio_sample_rates[16] = { - 96000, 88200, 64000, 48000, 44100, 32000, - 24000, 22050, 16000, 12000, 11025, 8000, 7350 -}; - /** bits needed to code codebook run value for long windows */ static const uint8_t run_value_bits_long[64] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, diff --git a/libavcodec/adts_header.c b/libavcodec/adts_header.c index e4454529c4..ff4efafbf7 100644 --- a/libavcodec/adts_header.c +++ b/libavcodec/adts_header.c @@ -40,7 +40,7 @@ int ff_adts_header_parse(GetBitContext *gbc, AACADTSHeaderInfo *hdr) crc_abs = get_bits1(gbc); /* protection_absent */ aot = get_bits(gbc, 2); /* profile_objecttype */ sr = get_bits(gbc, 4); /* sample_frequency_index */ - if (!avpriv_mpeg4audio_sample_rates[sr]) + if (!ff_mpeg4audio_sample_rates[sr]) return AAC_AC3_PARSE_ERROR_SAMPLE_RATE; skip_bits1(gbc); /* private_bit */ ch = get_bits(gbc, 3); /* channel_configuration */ @@ -63,7 +63,7 @@ int ff_adts_header_parse(GetBitContext *gbc, AACADTSHeaderInfo *hdr) hdr->crc_absent = crc_abs; hdr->num_aac_frames = rdb + 1; hdr->sampling_index = sr; - hdr->sample_rate = avpriv_mpeg4audio_sample_rates[sr]; + hdr->sample_rate = ff_mpeg4audio_sample_rates[sr]; hdr->samples = (rdb + 1) * 1024; hdr->bit_rate = size * 8 * hdr->sample_rate / hdr->samples; hdr->frame_length = size; diff --git a/libavcodec/mpeg4audio.c b/libavcodec/mpeg4audio.c index be50de9052..ed72a80f6d 100644 --- a/libavcodec/mpeg4audio.c +++ b/libavcodec/mpeg4audio.c @@ -57,13 +57,6 @@ static int parse_config_ALS(GetBitContext *gb, MPEG4AudioConfig *c, void *logctx return 0; } -/* XXX: make sure to update the copies in the different encoders if you change - * this table */ -const int avpriv_mpeg4audio_sample_rates[16] = { - 96000, 88200, 64000, 48000, 44100, 32000, - 24000, 22050, 16000, 12000, 11025, 8000, 7350 -}; - const uint8_t ff_mpeg4audio_channels[14] = { 0, 1, // mono (1/0) @@ -93,7 +86,7 @@ static inline int get_sample_rate(GetBitContext *gb, int *index) { *index = get_bits(gb, 4); return *index == 0x0f ? get_bits(gb, 24) : - avpriv_mpeg4audio_sample_rates[*index]; + ff_mpeg4audio_sample_rates[*index]; } int ff_mpeg4audio_get_config_gb(MPEG4AudioConfig *c, GetBitContext *gb, diff --git a/libavcodec/mpeg4audio.h b/libavcodec/mpeg4audio.h index 3187df68d2..c486a3ddef 100644 --- a/libavcodec/mpeg4audio.h +++ b/libavcodec/mpeg4audio.h @@ -27,7 +27,6 @@ #include "libavutil/attributes.h" #include "get_bits.h" -#include "internal.h" #include "put_bits.h" typedef struct MPEG4AudioConfig { @@ -45,7 +44,7 @@ typedef struct MPEG4AudioConfig { int frame_length_short; } MPEG4AudioConfig; -extern av_export_avcodec const int avpriv_mpeg4audio_sample_rates[16]; +extern const int ff_mpeg4audio_sample_rates[16]; extern const uint8_t ff_mpeg4audio_channels[14]; /** diff --git a/libavcodec/mpeg4audio_sample_rates.c b/libavcodec/mpeg4audio_sample_rates.c new file mode 100644 index 0000000000..b5ceb59c6e --- /dev/null +++ b/libavcodec/mpeg4audio_sample_rates.c @@ -0,0 +1,23 @@ +/* + * MPEG-4 Audio sample rates + * Copyright (c) 2008 Baptiste Coudurier + * Copyright (c) 2009 Alex Converse + * + * 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 "mpeg4audio_sample_rates.h" diff --git a/libavcodec/mpeg4audio_sample_rates.h b/libavcodec/mpeg4audio_sample_rates.h new file mode 100644 index 0000000000..0b8caa6d76 --- /dev/null +++ b/libavcodec/mpeg4audio_sample_rates.h @@ -0,0 +1,30 @@ +/* + * MPEG-4 Audio sample rates + * Copyright (c) 2008 Baptiste Coudurier + * Copyright (c) 2009 Alex Converse + * + * 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 + */ + +#ifndef AVCODEC_MPEG4AUDIO_SAMPLE_RATES_H +#define AVCODEC_MPEG4AUDIO_SAMPLE_RATES_H + +const int ff_mpeg4audio_sample_rates[16] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, 7350 +}; +#endif diff --git a/libavformat/Makefile b/libavformat/Makefile index f5d6b8fecf..6482f247b6 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -681,11 +681,14 @@ OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o # Objects duplicated from other libraries for shared builds SHLIBOBJS += log2_tab.o +SHLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o +SHLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o SHLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o -SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o jpegtables.o +SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o jpegtables.o \ + mpeg4audio_sample_rates.o SHLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o # libavdevice dependencies diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 31d1d93c23..66c530a2ff 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -24,6 +24,7 @@ #include "libavutil/intfloat.h" #include "libavutil/avassert.h" #include "libavutil/mathematics.h" +#include "libavcodec/mpeg4audio.h" #include "avio_internal.h" #include "avio.h" #include "avc.h" @@ -33,7 +34,6 @@ #include "metadata.h" #include "libavutil/opt.h" #include "libavcodec/put_bits.h" -#include "libavcodec/aacenctab.h" static const AVCodecTag flv_video_codec_ids[] = { @@ -514,7 +514,7 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i for (samplerate_index = 0; samplerate_index < 16; samplerate_index++) if (flv->audio_par->sample_rate - == mpeg4audio_sample_rates[samplerate_index]) + == ff_mpeg4audio_sample_rates[samplerate_index]) break; init_put_bits(&pbc, data, sizeof(data)); diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 6ce553205d..e271916bf1 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -2029,8 +2029,8 @@ static int matroska_aac_sri(int samplerate) { int sri; - for (sri = 0; sri < FF_ARRAY_ELEMS(avpriv_mpeg4audio_sample_rates); sri++) - if (avpriv_mpeg4audio_sample_rates[sri] == samplerate) + for (sri = 0; sri < FF_ARRAY_ELEMS(ff_mpeg4audio_sample_rates); sri++) + if (ff_mpeg4audio_sample_rates[sri] == samplerate) break; return sri; } diff --git a/libavformat/mpeg4audio_sample_rates.c b/libavformat/mpeg4audio_sample_rates.c new file mode 100644 index 0000000000..212385f348 --- /dev/null +++ b/libavformat/mpeg4audio_sample_rates.c @@ -0,0 +1,23 @@ +/* + * MPEG-4 Audio sample rates + * Copyright (c) 2008 Baptiste Coudurier + * Copyright (c) 2009 Alex Converse + * + * 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 "libavcodec/mpeg4audio_sample_rates.h" diff --git a/libavformat/sdp.c b/libavformat/sdp.c index 111a25b126..2230d74742 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -481,7 +481,7 @@ static int latm_context2config(AVFormatContext *s, const AVCodecParameters *par, *out = NULL; for (rate_index = 0; rate_index < 16; rate_index++) - if (avpriv_mpeg4audio_sample_rates[rate_index] == par->sample_rate) + if (ff_mpeg4audio_sample_rates[rate_index] == par->sample_rate) break; if (rate_index == 16) { av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); From 33e6d57f01dd4742a2e25ac5fa072b487d9d02ce Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 9 Mar 2021 12:15:35 +0100 Subject: [PATCH 34/38] avcodec/mpegaudiodata: Unavpriv mpa_bitrate and mpa_frequency tabs These arrays have a size of 180 resp. six bytes. This does not make it worthwhile to export them due to the overhead this occurs; for x64 Elf/Linux/GNU: 2x2B version, 2x24B .dynsym, 24B .rela.dyn, 8B .got, 4B hash + twice the size of the name (here 20+23B). Therefore these symbols are unavprived and duplicated for shared builds. Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 16 ++++++----- libavcodec/mp3_header_decompress_bsf.c | 5 ++-- libavcodec/mpegaudiodata.c | 13 --------- libavcodec/mpegaudiodata.h | 5 ++-- libavcodec/mpegaudiodecheader.c | 6 ++-- libavcodec/mpegaudioenc_template.c | 8 +++--- libavcodec/mpegaudiotabs.c | 22 +++++++++++++++ libavcodec/mpegaudiotabs.h | 39 ++++++++++++++++++++++++++ libavformat/Makefile | 3 ++ libavformat/isom.c | 2 +- libavformat/mp3enc.c | 8 +++--- libavformat/mpegaudiotabs.c | 22 +++++++++++++++ libavformat/nutenc.c | 4 +-- 13 files changed, 114 insertions(+), 39 deletions(-) create mode 100644 libavcodec/mpegaudiotabs.c create mode 100644 libavcodec/mpegaudiotabs.h create mode 100644 libavformat/mpegaudiotabs.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 63b4952eaf..5c045a15ea 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -123,7 +123,7 @@ OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ mpegaudiodsp_data.o \ mpegaudiodsp_fixed.o \ mpegaudiodsp_float.o -OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiodata.o +OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiotabs.o OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o mpeg4audio_sample_rates.o OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o rl.o \ mpegvideo_motion.o mpegutils.o \ @@ -474,9 +474,11 @@ OBJS-$(CONFIG_MP1_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP1FLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MP2_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP2_ENCODER) += mpegaudioenc_float.o mpegaudio.o \ - mpegaudiodata.o mpegaudiodsp_data.o + mpegaudiodata.o mpegaudiodsp_data.o \ + mpegaudiotabs.o OBJS-$(CONFIG_MP2FIXED_ENCODER) += mpegaudioenc_fixed.o mpegaudio.o \ - mpegaudiodata.o mpegaudiodsp_data.o + mpegaudiodata.o mpegaudiodsp_data.o \ + mpegaudiotabs.o OBJS-$(CONFIG_MP2FLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MP3_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP3_MF_ENCODER) += mfenc.o mf_utils.o @@ -990,18 +992,18 @@ OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec.o SHLIBOBJS += log2_tab.o reverse.o # General libavformat dependencies -OBJS-$(CONFIG_ISO_MEDIA) += mpegaudiodata.o - OBJS-$(CONFIG_FITS_DEMUXER) += fits.o -OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o # libavformat dependencies for static builds +STLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o STLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o +STLIBOBJS-$(CONFIG_MP3_MUXER) += mpegaudiotabs.o +STLIBOBJS-$(CONFIG_NUT_MUXER) += mpegaudiotabs.o STLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o jpegtables.o \ mpeg4audio_sample_rates.o @@ -1171,7 +1173,7 @@ OBJS-$(CONFIG_MJPEGA_DUMP_HEADER_BSF) += mjpega_dump_header_bsf.o OBJS-$(CONFIG_MPEG4_UNPACK_BFRAMES_BSF) += mpeg4_unpack_bframes_bsf.o OBJS-$(CONFIG_MOV2TEXTSUB_BSF) += movsub_bsf.o OBJS-$(CONFIG_MP3_HEADER_DECOMPRESS_BSF) += mp3_header_decompress_bsf.o \ - mpegaudiodata.o + mpegaudiotabs.o OBJS-$(CONFIG_MPEG2_METADATA_BSF) += mpeg2_metadata_bsf.o OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o OBJS-$(CONFIG_NULL_BSF) += null_bsf.o diff --git a/libavcodec/mp3_header_decompress_bsf.c b/libavcodec/mp3_header_decompress_bsf.c index 44c174c21c..ebf6bde1c2 100644 --- a/libavcodec/mp3_header_decompress_bsf.c +++ b/libavcodec/mp3_header_decompress_bsf.c @@ -22,6 +22,7 @@ #include "libavutil/intreadwrite.h" #include "bsf.h" #include "bsf_internal.h" +#include "defs.h" #include "mpegaudiodecheader.h" #include "mpegaudiodata.h" @@ -67,10 +68,10 @@ static int mp3_header_decompress(AVBSFContext *ctx, AVPacket *out) goto fail; } - sample_rate= avpriv_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); //in case sample rate is a little off + sample_rate = ff_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); //in case sample rate is a little off for(bitrate_index=2; bitrate_index<30; bitrate_index++){ - frame_size = avpriv_mpa_bitrate_tab[lsf][2][bitrate_index>>1]; + frame_size = ff_mpa_bitrate_tab[lsf][2][bitrate_index>>1]; frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index&1); if(frame_size == buf_size + 4) break; diff --git a/libavcodec/mpegaudiodata.c b/libavcodec/mpegaudiodata.c index 0569281109..669590908f 100644 --- a/libavcodec/mpegaudiodata.c +++ b/libavcodec/mpegaudiodata.c @@ -26,19 +26,6 @@ #include "mpegaudiodata.h" - -const uint16_t avpriv_mpa_bitrate_tab[2][3][15] = { - { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }, - {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }, - {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } }, - { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160} - } -}; - -const uint16_t avpriv_mpa_freq_tab[3] = { 44100, 48000, 32000 }; - /*******************************************************/ /* layer 2 tables */ diff --git a/libavcodec/mpegaudiodata.h b/libavcodec/mpegaudiodata.h index 0a425ef6a8..a4148a1ffe 100644 --- a/libavcodec/mpegaudiodata.h +++ b/libavcodec/mpegaudiodata.h @@ -31,14 +31,13 @@ #include "config.h" -#include "internal.h" #include "vlc.h" #define MODE_EXT_MS_STEREO 2 #define MODE_EXT_I_STEREO 1 -extern av_export_avcodec const uint16_t avpriv_mpa_bitrate_tab[2][3][15]; -extern av_export_avcodec const uint16_t avpriv_mpa_freq_tab[3]; +extern const uint16_t ff_mpa_bitrate_tab[2][3][15]; +extern const uint16_t ff_mpa_freq_tab[3]; extern const int ff_mpa_sblimit_table[5]; extern const int ff_mpa_quant_steps[17]; extern const int ff_mpa_quant_bits[17]; diff --git a/libavcodec/mpegaudiodecheader.c b/libavcodec/mpegaudiodecheader.c index 93c5f3d8f8..446a6e29d8 100644 --- a/libavcodec/mpegaudiodecheader.c +++ b/libavcodec/mpegaudiodecheader.c @@ -52,9 +52,9 @@ int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header) s->layer = 4 - ((header >> 17) & 3); /* extract frequency */ sample_rate_index = (header >> 10) & 3; - if (sample_rate_index >= FF_ARRAY_ELEMS(avpriv_mpa_freq_tab)) + if (sample_rate_index >= FF_ARRAY_ELEMS(ff_mpa_freq_tab)) sample_rate_index = 0; - sample_rate = avpriv_mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25); + sample_rate = ff_mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25); sample_rate_index += 3 * (s->lsf + mpeg25); s->sample_rate_index = sample_rate_index; s->error_protection = ((header >> 16) & 1) ^ 1; @@ -75,7 +75,7 @@ int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header) s->nb_channels = 2; if (bitrate_index != 0) { - frame_size = avpriv_mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index]; + frame_size = ff_mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index]; s->bit_rate = frame_size * 1000; switch(s->layer) { case 1: diff --git a/libavcodec/mpegaudioenc_template.c b/libavcodec/mpegaudioenc_template.c index 1df3cc704a..1ffd31f7cb 100644 --- a/libavcodec/mpegaudioenc_template.c +++ b/libavcodec/mpegaudioenc_template.c @@ -95,9 +95,9 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx) /* encoding freq */ s->lsf = 0; for(i=0;i<3;i++) { - if (avpriv_mpa_freq_tab[i] == freq) + if (ff_mpa_freq_tab[i] == freq) break; - if ((avpriv_mpa_freq_tab[i] / 2) == freq) { + if ((ff_mpa_freq_tab[i] / 2) == freq) { s->lsf = 1; break; } @@ -110,12 +110,12 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx) /* encoding bitrate & frequency */ for(i=1;i<15;i++) { - if (avpriv_mpa_bitrate_tab[s->lsf][1][i] == bitrate) + if (ff_mpa_bitrate_tab[s->lsf][1][i] == bitrate) break; } if (i == 15 && !avctx->bit_rate) { i = 14; - bitrate = avpriv_mpa_bitrate_tab[s->lsf][1][i]; + bitrate = ff_mpa_bitrate_tab[s->lsf][1][i]; avctx->bit_rate = bitrate * 1000; } if (i == 15){ diff --git a/libavcodec/mpegaudiotabs.c b/libavcodec/mpegaudiotabs.c new file mode 100644 index 0000000000..eaa380c808 --- /dev/null +++ b/libavcodec/mpegaudiotabs.c @@ -0,0 +1,22 @@ +/* + * MPEG Audio common tables + * copyright (c) 2002 Fabrice Bellard + * + * 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 "mpegaudiotabs.h" diff --git a/libavcodec/mpegaudiotabs.h b/libavcodec/mpegaudiotabs.h new file mode 100644 index 0000000000..671b83848d --- /dev/null +++ b/libavcodec/mpegaudiotabs.h @@ -0,0 +1,39 @@ +/* + * MPEG Audio common tables + * copyright (c) 2002 Fabrice Bellard + * + * 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 + */ + +#ifndef AVCODEC_MPEGAUDIOTABS_H +#define AVCODEC_MPEGAUDIOTABS_H + +#include + +const uint16_t ff_mpa_bitrate_tab[2][3][15] = { + { { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }, + { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }, + { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } }, + { { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 }, + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 }, + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 } + } +}; + +const uint16_t ff_mpa_freq_tab[3] = { 44100, 48000, 32000 }; + +#endif diff --git a/libavformat/Makefile b/libavformat/Makefile index 6482f247b6..892189d66a 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -681,11 +681,14 @@ OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o # Objects duplicated from other libraries for shared builds SHLIBOBJS += log2_tab.o +SHLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o SHLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o SHLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o +SHLIBOBJS-$(CONFIG_MP3_MUXER) += mpegaudiotabs.o SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o +SHLIBOBJS-$(CONFIG_NUT_MUXER) += mpegaudiotabs.o SHLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o jpegtables.o \ mpeg4audio_sample_rates.o diff --git a/libavformat/isom.c b/libavformat/isom.c index 300ba927c2..015c82e1bb 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -362,7 +362,7 @@ int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext return ret; st->codecpar->channels = cfg.channels; if (cfg.object_type == 29 && cfg.sampling_index < 3) // old mp3on4 - st->codecpar->sample_rate = avpriv_mpa_freq_tab[cfg.sampling_index]; + st->codecpar->sample_rate = ff_mpa_freq_tab[cfg.sampling_index]; else if (cfg.ext_sample_rate) st->codecpar->sample_rate = cfg.ext_sample_rate; else diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index 5728ef30be..0ffc79c025 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -159,8 +159,8 @@ static int mp3_write_xing(AVFormatContext *s) if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) || !mp3->write_xing) return 0; - for (i = 0; i < FF_ARRAY_ELEMS(avpriv_mpa_freq_tab); i++) { - const uint16_t base_freq = avpriv_mpa_freq_tab[i]; + for (i = 0; i < FF_ARRAY_ELEMS(ff_mpa_freq_tab); i++) { + const uint16_t base_freq = ff_mpa_freq_tab[i]; if (par->sample_rate == base_freq) ver = 0x3; // MPEG 1 else if (par->sample_rate == base_freq / 2) ver = 0x2; // MPEG 2 @@ -170,7 +170,7 @@ static int mp3_write_xing(AVFormatContext *s) srate_idx = i; break; } - if (i == FF_ARRAY_ELEMS(avpriv_mpa_freq_tab)) { + if (i == FF_ARRAY_ELEMS(ff_mpa_freq_tab)) { av_log(s, AV_LOG_WARNING, "Unsupported sample rate, not writing Xing header.\n"); return -1; } @@ -190,7 +190,7 @@ static int mp3_write_xing(AVFormatContext *s) header |= channels << 6; for (bitrate_idx = 1; bitrate_idx < 15; bitrate_idx++) { - int bit_rate = 1000 * avpriv_mpa_bitrate_tab[ver != 3][3 - 1][bitrate_idx]; + int bit_rate = 1000 * ff_mpa_bitrate_tab[ver != 3][3 - 1][bitrate_idx]; int error = FFABS(bit_rate - par->bit_rate); if (error < best_bitrate_error) { diff --git a/libavformat/mpegaudiotabs.c b/libavformat/mpegaudiotabs.c new file mode 100644 index 0000000000..41ac76e21b --- /dev/null +++ b/libavformat/mpegaudiotabs.c @@ -0,0 +1,22 @@ +/* + * MPEG Audio common tables + * copyright (c) 2002 Fabrice Bellard + * + * 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 "libavcodec/mpegaudiotabs.h" diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c index 7977980935..585ce953ca 100644 --- a/libavformat/nutenc.c +++ b/libavformat/nutenc.c @@ -70,11 +70,11 @@ static int find_expected_header(AVCodecParameters *p, int size, int key_frame, else if (sample_rate < (44100 + 48000) / 2) sample_rate_index = 0; else sample_rate_index = 1; - sample_rate = avpriv_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); + sample_rate = ff_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); for (bitrate_index = 2; bitrate_index < 30; bitrate_index++) { frame_size = - avpriv_mpa_bitrate_tab[lsf][layer - 1][bitrate_index >> 1]; + ff_mpa_bitrate_tab[lsf][layer - 1][bitrate_index >> 1]; frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index & 1); From 007ffbeb533af512b08851435ce78e1b15e8e1e0 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Dec 2021 19:32:03 +0100 Subject: [PATCH 35/38] avcodec/internal: Remove unused av_export_avcodec Signed-off-by: Andreas Rheinhardt --- libavcodec/internal.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libavcodec/internal.h b/libavcodec/internal.h index a62f8dbd4e..d3ee0214c5 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -363,10 +363,4 @@ int ff_int_from_list_or_default(void *ctx, const char * val_name, int val, void ff_dvdsub_parse_palette(uint32_t *palette, const char *p); -#if defined(_WIN32) && CONFIG_SHARED && !defined(BUILDING_avcodec) -# define av_export_avcodec __declspec(dllimport) -#else -# define av_export_avcodec -#endif - #endif /* AVCODEC_INTERNAL_H */ From b74e47c4ff5bca998936c0d8b9a0892104a7403d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 13 Dec 2021 19:55:39 +0100 Subject: [PATCH 36/38] avcodec/utils: Unavpriv avpriv_toupper4() This function is quite small (96B with GCC 11.2 on x64 Ubuntu 21.10 at -O3), making it more economical to duplicate it into libavformat instead of exporting it as avpriv: Doing so saves 2x24B in .dynsim, 2x16B in .dynstr, 2x2B .gnu.version, 24B in .rela.plt, 16B in .plt, 16B in .plt.sec (if enabled), 4B .gnu.hash; besides the actual duplicated code this also adds 2x8B .eh_frame_hdr and 24B .eh_frame. In other words: Duplicating is neutral size-wise (it is also presumed neutral for other systems). Given that it avoids the runtime overhead of dynamic symbols, it is advantageouos to duplicate the function. Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 4 +++- libavcodec/internal.h | 2 +- libavcodec/mpeg12dec.c | 2 +- libavcodec/mpegvideo.c | 2 +- libavcodec/to_upper4.c | 23 +++++++++++++++++++++++ libavcodec/to_upper4.h | 37 +++++++++++++++++++++++++++++++++++++ libavcodec/utils.c | 8 -------- libavformat/Makefile | 2 +- libavformat/movenc.c | 2 +- libavformat/mux.c | 2 +- libavformat/to_upper4.c | 23 +++++++++++++++++++++++ libavformat/utils.c | 2 +- 12 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 libavcodec/to_upper4.c create mode 100644 libavcodec/to_upper4.h create mode 100644 libavformat/to_upper4.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5c045a15ea..81a11a3688 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -127,7 +127,8 @@ OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiotabs.o OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o mpeg4audio_sample_rates.o OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o rl.o \ mpegvideo_motion.o mpegutils.o \ - mpegvideodata.o mpegpicture.o + mpegvideodata.o mpegpicture.o \ + to_upper4.o OBJS-$(CONFIG_MPEGVIDEOENC) += mpegvideo_enc.o mpeg12data.o \ motion_est.o ratecontrol.o \ mpegvideoencdsp.o @@ -996,6 +997,7 @@ OBJS-$(CONFIG_FITS_DEMUXER) += fits.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o # libavformat dependencies for static builds +STLIBOBJS-$(CONFIG_AVFORMAT) += to_upper4.o STLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o STLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o diff --git a/libavcodec/internal.h b/libavcodec/internal.h index d3ee0214c5..72ca1553f6 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -225,7 +225,7 @@ extern const uint8_t ff_log2_run[41]; */ int ff_match_2uint16(const uint16_t (*tab)[2], int size, int a, int b); -unsigned int avpriv_toupper4(unsigned int x); +unsigned int ff_toupper4(unsigned int x); void ff_color_frame(AVFrame *frame, const int color[4]); diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 672031b6db..cf06af0a71 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -2832,7 +2832,7 @@ static int mpeg_decode_frame(AVCodecContext *avctx, void *data, } #endif - s2->codec_tag = avpriv_toupper4(avctx->codec_tag); + s2->codec_tag = ff_toupper4(avctx->codec_tag); if (s->mpeg_enc_ctx_allocated == 0 && ( s2->codec_tag == AV_RL32("VCR2") || s2->codec_tag == AV_RL32("BW10") )) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 46e56ca08e..a974650133 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -701,7 +701,7 @@ void ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx) s->workaround_bugs = avctx->workaround_bugs; /* convert fourcc to upper case */ - s->codec_tag = avpriv_toupper4(avctx->codec_tag); + s->codec_tag = ff_toupper4(avctx->codec_tag); } /** diff --git a/libavcodec/to_upper4.c b/libavcodec/to_upper4.c new file mode 100644 index 0000000000..29f65bf5c3 --- /dev/null +++ b/libavcodec/to_upper4.c @@ -0,0 +1,23 @@ +/* + * Converting FOURCCs to uppercase + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * 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 "to_upper4.h" diff --git a/libavcodec/to_upper4.h b/libavcodec/to_upper4.h new file mode 100644 index 0000000000..d9648b5ef6 --- /dev/null +++ b/libavcodec/to_upper4.h @@ -0,0 +1,37 @@ +/* + * Converting FOURCCs to uppercase + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * 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 + */ + +#ifndef AVCODEC_TO_UPPER4_H +#define AVCODEC_TO_UPPER4_H + +#include "libavutil/avstring.h" +#include "internal.h" + +unsigned int ff_toupper4(unsigned int x) +{ + return av_toupper(x & 0xFF) | + (av_toupper((x >> 8) & 0xFF) << 8) | + (av_toupper((x >> 16) & 0xFF) << 16) | +((unsigned)av_toupper((x >> 24) & 0xFF) << 24); +} + +#endif diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 4d236ff1cd..b19befef21 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -863,14 +863,6 @@ const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index) return &codec->hw_configs[index]->public; } -unsigned int avpriv_toupper4(unsigned int x) -{ - return av_toupper(x & 0xFF) + - (av_toupper((x >> 8) & 0xFF) << 8) + - (av_toupper((x >> 16) & 0xFF) << 16) + -((unsigned)av_toupper((x >> 24) & 0xFF) << 24); -} - int ff_thread_ref_frame(ThreadFrame *dst, const ThreadFrame *src) { int ret; diff --git a/libavformat/Makefile b/libavformat/Makefile index 892189d66a..8aba9d164c 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -680,7 +680,7 @@ OBJS-$(CONFIG_LIBSSH_PROTOCOL) += libssh.o OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o # Objects duplicated from other libraries for shared builds -SHLIBOBJS += log2_tab.o +SHLIBOBJS += log2_tab.o to_upper4.o SHLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o SHLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o diff --git a/libavformat/movenc.c b/libavformat/movenc.c index bc6abcfcaa..5d4429b82e 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1717,7 +1717,7 @@ static unsigned int validate_codec_tag(const AVCodecTag *const *tags, for (i = 0; tags && tags[i]; i++) { const AVCodecTag *codec_tags = tags[i]; while (codec_tags->id != AV_CODEC_ID_NONE) { - if (avpriv_toupper4(codec_tags->tag) == avpriv_toupper4(tag) && + if (ff_toupper4(codec_tags->tag) == ff_toupper4(tag) && codec_tags->id == codec_id) return codec_tags->tag; codec_tags++; diff --git a/libavformat/mux.c b/libavformat/mux.c index 3ba95d28c6..0500f636de 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -204,7 +204,7 @@ static int validate_codec_tag(AVFormatContext *s, AVStream *st) for (int n = 0; s->oformat->codec_tag[n]; n++) { avctag = s->oformat->codec_tag[n]; while (avctag->id != AV_CODEC_ID_NONE) { - if (avpriv_toupper4(avctag->tag) == avpriv_toupper4(st->codecpar->codec_tag)) { + if (ff_toupper4(avctag->tag) == ff_toupper4(st->codecpar->codec_tag)) { id = avctag->id; if (id == st->codecpar->codec_id) return 1; diff --git a/libavformat/to_upper4.c b/libavformat/to_upper4.c new file mode 100644 index 0000000000..e84c803675 --- /dev/null +++ b/libavformat/to_upper4.c @@ -0,0 +1,23 @@ +/* + * Converting FOURCCs to uppercase + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * 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 "libavcodec/to_upper4.h" diff --git a/libavformat/utils.c b/libavformat/utils.c index 23e81bda9d..ca6185b5c3 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -361,7 +361,7 @@ enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag) if (tag == tags[i].tag) return tags[i].id; for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++) - if (avpriv_toupper4(tag) == avpriv_toupper4(tags[i].tag)) + if (ff_toupper4(tag) == ff_toupper4(tags[i].tag)) return tags[i].id; return AV_CODEC_ID_NONE; } From d61240f8c95e9cf7a0aaef2bb4495960d3fec62c Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Thu, 16 Dec 2021 01:49:39 +0100 Subject: [PATCH 37/38] avcodec/packet_internal: Add proper PacketList struct Up until now, we had a PacketList structure which is actually a PacketListEntry; a proper PacketList did not exist and all the related functions just passed pointers to pointers to the head and tail elements around. All these pointers were actually consecutive elements of their containing structs, i.e. the users already treated them as if they were a struct. So add a proper PacketList struct and rename the current PacketList to PacketListEntry; also make the functions use this structure instead of the pair of pointers. Signed-off-by: Andreas Rheinhardt --- libavcodec/avpacket.c | 36 +++++++++++------------ libavcodec/packet_internal.h | 25 +++++++--------- libavdevice/decklink_common.h | 5 +++- libavdevice/decklink_dec.cpp | 29 +++++++++---------- libavdevice/dshow.c | 10 +++---- libavdevice/dshow_capture.h | 2 +- libavdevice/vfwcap.c | 12 ++++---- libavformat/aiffenc.c | 17 ++++++----- libavformat/demux.c | 54 ++++++++++++++++------------------- libavformat/flacenc.c | 10 +++---- libavformat/internal.h | 12 ++++---- libavformat/matroskadec.c | 19 ++++++------ libavformat/movenc.c | 6 ++-- libavformat/movenc.h | 2 +- libavformat/movenc_ttml.c | 6 ++-- libavformat/mp3enc.c | 11 ++++--- libavformat/mux.c | 38 ++++++++++++------------ libavformat/mxfenc.c | 14 ++++----- libavformat/ttaenc.c | 13 ++++----- libavformat/utils.c | 7 ++--- 20 files changed, 153 insertions(+), 175 deletions(-) diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index a0134e405c..4f7a6b255c 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -535,13 +535,12 @@ void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb) pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb); } -int avpriv_packet_list_put(PacketList **packet_buffer, - PacketList **plast_pktl, +int avpriv_packet_list_put(PacketList *packet_buffer, AVPacket *pkt, int (*copy)(AVPacket *dst, const AVPacket *src), int flags) { - PacketList *pktl = av_malloc(sizeof(PacketList)); + PacketListEntry *pktl = av_malloc(sizeof(*pktl)); int ret; if (!pktl) @@ -565,44 +564,41 @@ int avpriv_packet_list_put(PacketList **packet_buffer, pktl->next = NULL; - if (*packet_buffer) - (*plast_pktl)->next = pktl; + if (packet_buffer->head) + packet_buffer->tail->next = pktl; else - *packet_buffer = pktl; + packet_buffer->head = pktl; /* Add the packet in the buffered packet list. */ - *plast_pktl = pktl; + packet_buffer->tail = pktl; return 0; } -int avpriv_packet_list_get(PacketList **pkt_buffer, - PacketList **pkt_buffer_end, +int avpriv_packet_list_get(PacketList *pkt_buffer, AVPacket *pkt) { - PacketList *pktl; - if (!*pkt_buffer) + PacketListEntry *pktl = pkt_buffer->head; + if (!pktl) return AVERROR(EAGAIN); - pktl = *pkt_buffer; *pkt = pktl->pkt; - *pkt_buffer = pktl->next; - if (!pktl->next) - *pkt_buffer_end = NULL; + pkt_buffer->head = pktl->next; + if (!pkt_buffer->head) + pkt_buffer->tail = NULL; av_freep(&pktl); return 0; } -void avpriv_packet_list_free(PacketList **pkt_buf, PacketList **pkt_buf_end) +void avpriv_packet_list_free(PacketList *pkt_buf) { - PacketList *tmp = *pkt_buf; + PacketListEntry *tmp = pkt_buf->head; while (tmp) { - PacketList *pktl = tmp; + PacketListEntry *pktl = tmp; tmp = pktl->next; av_packet_unref(&pktl->pkt); av_freep(&pktl); } - *pkt_buf = NULL; - *pkt_buf_end = NULL; + pkt_buf->head = pkt_buf->tail = NULL; } int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type) diff --git a/libavcodec/packet_internal.h b/libavcodec/packet_internal.h index a10931c106..92a0d4e6d5 100644 --- a/libavcodec/packet_internal.h +++ b/libavcodec/packet_internal.h @@ -23,16 +23,19 @@ #include "packet.h" -typedef struct PacketList { - struct PacketList *next; +typedef struct PacketListEntry { + struct PacketListEntry *next; AVPacket pkt; +} PacketListEntry; + +typedef struct PacketList { + PacketListEntry *head, *tail; } PacketList; /** * Append an AVPacket to the list. * - * @param head List head element - * @param tail List tail element + * @param list A PacketList * @param pkt The packet being appended. The data described in it will * be made reference counted if it isn't already. * @param copy A callback to copy the contents of the packet to the list. @@ -41,8 +44,7 @@ typedef struct PacketList { * @return 0 on success, negative AVERROR value on failure. On failure, the packet and the list are unchanged. */ -int avpriv_packet_list_put(PacketList **head, PacketList **tail, - AVPacket *pkt, +int avpriv_packet_list_put(PacketList *list, AVPacket *pkt, int (*copy)(AVPacket *dst, const AVPacket *src), int flags); @@ -52,22 +54,17 @@ int avpriv_packet_list_put(PacketList **head, PacketList **tail, * @note The pkt will be overwritten completely on success. The caller * owns the packet and must unref it by itself. * - * @param head List head element - * @param tail List tail element + * @param head A pointer to a PacketList struct * @param pkt Pointer to an AVPacket struct * @return 0 on success, and a packet is returned. AVERROR(EAGAIN) if * the list was empty. */ -int avpriv_packet_list_get(PacketList **head, PacketList **tail, - AVPacket *pkt); +int avpriv_packet_list_get(PacketList *list, AVPacket *pkt); /** * Wipe the list and unref all the packets in it. - * - * @param head List head element - * @param tail List tail element */ -void avpriv_packet_list_free(PacketList **head, PacketList **tail); +void avpriv_packet_list_free(PacketList *list); int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type); diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index 5b11dcd46d..79d6ac5b38 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -29,6 +29,9 @@ #define IDeckLinkProfileAttributes IDeckLinkAttributes #endif +extern "C" { +#include "libavcodec/packet_internal.h" +} #include "libavutil/thread.h" #include "decklink_common_c.h" #if CONFIG_LIBKLVANC @@ -75,7 +78,7 @@ class decklink_output_callback; class decklink_input_callback; typedef struct AVPacketQueue { - PacketList *first_pkt, *last_pkt; + PacketList pkt_list; int nb_packets; unsigned long long size; int abort_request; diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 491fe4be3d..c97a72d93d 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -483,16 +483,16 @@ static void avpacket_queue_init(AVFormatContext *avctx, AVPacketQueue *q) static void avpacket_queue_flush(AVPacketQueue *q) { - PacketList *pkt, *pkt1; + PacketListEntry *pkt, *pkt1; pthread_mutex_lock(&q->mutex); - for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) { + for (pkt = q->pkt_list.head; pkt != NULL; pkt = pkt1) { pkt1 = pkt->next; av_packet_unref(&pkt->pkt); av_freep(&pkt); } - q->last_pkt = NULL; - q->first_pkt = NULL; + q->pkt_list.head = NULL; + q->pkt_list.tail = NULL; q->nb_packets = 0; q->size = 0; pthread_mutex_unlock(&q->mutex); @@ -516,7 +516,7 @@ static unsigned long long avpacket_queue_size(AVPacketQueue *q) static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) { - PacketList *pkt1; + PacketListEntry *pkt1; // Drop Packet if queue size is > maximum queue size if (avpacket_queue_size(q) > (uint64_t)q->max_q_size) { @@ -530,7 +530,7 @@ static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) return -1; } - pkt1 = (PacketList *)av_malloc(sizeof(PacketList)); + pkt1 = (PacketListEntry *)av_malloc(sizeof(*pkt1)); if (!pkt1) { av_packet_unref(pkt); return -1; @@ -540,13 +540,13 @@ static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) pthread_mutex_lock(&q->mutex); - if (!q->last_pkt) { - q->first_pkt = pkt1; + if (!q->pkt_list.tail) { + q->pkt_list.head = pkt1; } else { - q->last_pkt->next = pkt1; + q->pkt_list.tail->next = pkt1; } - q->last_pkt = pkt1; + q->pkt_list.tail = pkt1; q->nb_packets++; q->size += pkt1->pkt.size + sizeof(*pkt1); @@ -558,17 +558,16 @@ static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) static int avpacket_queue_get(AVPacketQueue *q, AVPacket *pkt, int block) { - PacketList *pkt1; int ret; pthread_mutex_lock(&q->mutex); for (;; ) { - pkt1 = q->first_pkt; + PacketListEntry *pkt1 = q->pkt_list.head; if (pkt1) { - q->first_pkt = pkt1->next; - if (!q->first_pkt) { - q->last_pkt = NULL; + q->pkt_list.head = pkt1->next; + if (!q->pkt_list.head) { + q->pkt_list.tail = NULL; } q->nb_packets--; q->size -= pkt1->pkt.size + sizeof(*pkt1); diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 7e04880b38..3a16f3720f 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -238,7 +238,7 @@ static int dshow_read_close(AVFormatContext *s) { struct dshow_ctx *ctx = s->priv_data; - PacketList *pktl; + PacketListEntry *pktl; if (ctx->control) { IMediaControl_Stop(ctx->control); @@ -298,7 +298,7 @@ dshow_read_close(AVFormatContext *s) pktl = ctx->pktl; while (pktl) { - PacketList *next = pktl->next; + PacketListEntry *next = pktl->next; av_packet_unref(&pktl->pkt); av_free(pktl); pktl = next; @@ -342,7 +342,7 @@ callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, e { AVFormatContext *s = priv_data; struct dshow_ctx *ctx = s->priv_data; - PacketList **ppktl, *pktl_next; + PacketListEntry **ppktl, *pktl_next; // dump_videohdr(s, vdhdr); @@ -351,7 +351,7 @@ callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, e if(shall_we_drop(s, index, devtype)) goto fail; - pktl_next = av_mallocz(sizeof(PacketList)); + pktl_next = av_mallocz(sizeof(*pktl_next)); if(!pktl_next) goto fail; @@ -1868,7 +1868,7 @@ static int dshow_check_event_queue(IMediaEvent *media_event) static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt) { struct dshow_ctx *ctx = s->priv_data; - PacketList *pktl = NULL; + PacketListEntry *pktl = NULL; while (!ctx->eof && !pktl) { WaitForSingleObject(ctx->mutex, INFINITE); diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index 21f5cf7e83..b548cd7afc 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -322,7 +322,7 @@ struct dshow_ctx { HANDLE mutex; HANDLE event[2]; /* event[0] is set by DirectShow * event[1] is set by callback() */ - PacketList *pktl; + PacketListEntry *pktl; int eof; diff --git a/libavdevice/vfwcap.c b/libavdevice/vfwcap.c index 6fad466f8a..86a40b4af4 100644 --- a/libavdevice/vfwcap.c +++ b/libavdevice/vfwcap.c @@ -45,7 +45,7 @@ struct vfw_ctx { HWND hwnd; HANDLE mutex; HANDLE event; - PacketList *pktl; + PacketListEntry *pktl; unsigned int curbufsize; unsigned int frame_num; char *video_size; /**< A string describing video size, set by a private option. */ @@ -179,7 +179,7 @@ static LRESULT CALLBACK videostream_cb(HWND hwnd, LPVIDEOHDR vdhdr) { AVFormatContext *s; struct vfw_ctx *ctx; - PacketList **ppktl, *pktl_next; + PacketListEntry **ppktl, *pktl_next; s = (AVFormatContext *) GetWindowLongPtr(hwnd, GWLP_USERDATA); ctx = s->priv_data; @@ -191,7 +191,7 @@ static LRESULT CALLBACK videostream_cb(HWND hwnd, LPVIDEOHDR vdhdr) WaitForSingleObject(ctx->mutex, INFINITE); - pktl_next = av_mallocz(sizeof(PacketList)); + pktl_next = av_mallocz(sizeof(*pktl_next)); if(!pktl_next) goto fail; @@ -220,7 +220,7 @@ fail: static int vfw_read_close(AVFormatContext *s) { struct vfw_ctx *ctx = s->priv_data; - PacketList *pktl; + PacketListEntry *pktl; if(ctx->hwnd) { SendMessage(ctx->hwnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0); @@ -234,7 +234,7 @@ static int vfw_read_close(AVFormatContext *s) pktl = ctx->pktl; while (pktl) { - PacketList *next = pktl->next; + PacketListEntry *next = pktl->next; av_packet_unref(&pktl->pkt); av_free(pktl); pktl = next; @@ -440,7 +440,7 @@ fail: static int vfw_read_packet(AVFormatContext *s, AVPacket *pkt) { struct vfw_ctx *ctx = s->priv_data; - PacketList *pktl = NULL; + PacketListEntry *pktl = NULL; while(!pktl) { WaitForSingleObject(ctx->mutex, INFINITE); diff --git a/libavformat/aiffenc.c b/libavformat/aiffenc.c index 7bb0978a53..1fd6b8a70b 100644 --- a/libavformat/aiffenc.c +++ b/libavformat/aiffenc.c @@ -37,7 +37,7 @@ typedef struct AIFFOutputContext { int64_t frames; int64_t ssnd; int audio_stream_idx; - PacketList *pict_list, *pict_list_end; + PacketList pict_list; int write_id3v2; int id3v2_version; } AIFFOutputContext; @@ -48,9 +48,9 @@ static int put_id3v2_tags(AVFormatContext *s, AIFFOutputContext *aiff) uint64_t pos, end, size; ID3v2EncContext id3v2 = { 0 }; AVIOContext *pb = s->pb; - PacketList *pict_list = aiff->pict_list; + PacketListEntry *list_entry = aiff->pict_list.head; - if (!s->metadata && !s->nb_chapters && !aiff->pict_list) + if (!s->metadata && !s->nb_chapters && !list_entry) return 0; avio_wl32(pb, MKTAG('I', 'D', '3', ' ')); @@ -59,10 +59,10 @@ static int put_id3v2_tags(AVFormatContext *s, AIFFOutputContext *aiff) ff_id3v2_start(&id3v2, pb, aiff->id3v2_version, ID3v2_DEFAULT_MAGIC); ff_id3v2_write_metadata(s, &id3v2); - while (pict_list) { - if ((ret = ff_id3v2_write_apic(s, &id3v2, &pict_list->pkt)) < 0) + while (list_entry) { + if ((ret = ff_id3v2_write_apic(s, &id3v2, &list_entry->pkt)) < 0) return ret; - pict_list = pict_list->next; + list_entry = list_entry->next; } ff_id3v2_finish(&id3v2, pb, s->metadata_header_padding); @@ -218,8 +218,7 @@ static int aiff_write_packet(AVFormatContext *s, AVPacket *pkt) if (s->streams[pkt->stream_index]->nb_frames >= 1) return 0; - return avpriv_packet_list_put(&aiff->pict_list, &aiff->pict_list_end, - pkt, NULL, 0); + return avpriv_packet_list_put(&aiff->pict_list, pkt, NULL, 0); } return 0; @@ -265,7 +264,7 @@ static void aiff_deinit(AVFormatContext *s) { AIFFOutputContext *aiff = s->priv_data; - avpriv_packet_list_free(&aiff->pict_list, &aiff->pict_list_end); + avpriv_packet_list_free(&aiff->pict_list); } #define OFFSET(x) offsetof(AIFFOutputContext, x) diff --git a/libavformat/demux.c b/libavformat/demux.c index 4770e5517f..f895f0ba85 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -537,7 +537,7 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif for (;;) { - PacketList *pktl = si->raw_packet_buffer; + PacketListEntry *pktl = si->raw_packet_buffer.head; AVStream *st; FFStream *sti; const AVPacket *pkt1; @@ -548,8 +548,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if ((err = probe_codec(s, st, NULL)) < 0) return err; if (ffstream(st)->request_probe <= 0) { - avpriv_packet_list_get(&si->raw_packet_buffer, - &si->raw_packet_buffer_end, pkt); + avpriv_packet_list_get(&si->raw_packet_buffer, pkt); si->raw_packet_buffer_size -= pkt->size; return 0; } @@ -624,13 +623,12 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; err = avpriv_packet_list_put(&si->raw_packet_buffer, - &si->raw_packet_buffer_end, pkt, NULL, 0); if (err < 0) { av_packet_unref(pkt); return err; } - pkt1 = &si->raw_packet_buffer_end->pkt; + pkt1 = &si->raw_packet_buffer.tail->pkt; si->raw_packet_buffer_size += pkt1->size; if ((err = probe_codec(s, st, pkt1)) < 0) @@ -716,13 +714,14 @@ static int has_decode_delay_been_guessed(AVStream *st) return sti->nb_decoded_frames >= 20; } -static PacketList *get_next_pkt(AVFormatContext *s, AVStream *st, PacketList *pktl) +static PacketListEntry *get_next_pkt(AVFormatContext *s, AVStream *st, + PacketListEntry *pktl) { FFFormatContext *const si = ffformatcontext(s); if (pktl->next) return pktl->next; - if (pktl == si->packet_buffer_end) - return si->parse_queue; + if (pktl == si->packet_buffer.tail) + return si->parse_queue.head; return NULL; } @@ -774,7 +773,7 @@ static int64_t select_from_pts_buffer(AVStream *st, int64_t *pts_buffer, int64_t * of the packets in a window. */ static void update_dts_from_pts(AVFormatContext *s, int stream_index, - PacketList *pkt_buffer) + PacketListEntry *pkt_buffer) { AVStream *const st = s->streams[stream_index]; int delay = ffstream(st)->avctx->has_b_frames; @@ -804,7 +803,7 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, FFFormatContext *const si = ffformatcontext(s); AVStream *const st = s->streams[stream_index]; FFStream *const sti = ffstream(st); - PacketList *pktl = si->packet_buffer ? si->packet_buffer : si->parse_queue; + PacketListEntry *pktl = si->packet_buffer.head ? si->packet_buffer.head : si->parse_queue.head; uint64_t shift; @@ -823,7 +822,7 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, if (is_relative(pts)) pts += shift; - for (PacketList *pktl_it = pktl; pktl_it; pktl_it = get_next_pkt(s, st, pktl_it)) { + for (PacketListEntry *pktl_it = pktl; pktl_it; pktl_it = get_next_pkt(s, st, pktl_it)) { if (pktl_it->pkt.stream_index != stream_index) continue; if (is_relative(pktl_it->pkt.pts)) @@ -856,7 +855,7 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st, { FFFormatContext *const si = ffformatcontext(s); FFStream *const sti = ffstream(st); - PacketList *pktl = si->packet_buffer ? si->packet_buffer : si->parse_queue; + PacketListEntry *pktl = si->packet_buffer.head ? si->packet_buffer.head : si->parse_queue.head; int64_t cur_dts = RELATIVE_TS_BASE; if (sti->first_dts != AV_NOPTS_VALUE) { @@ -882,7 +881,7 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st, av_log(s, AV_LOG_DEBUG, "first_dts %s but no packet with dts in the queue\n", av_ts2str(sti->first_dts)); return; } - pktl = si->packet_buffer ? si->packet_buffer : si->parse_queue; + pktl = si->packet_buffer.head ? si->packet_buffer.head : si->parse_queue.head; sti->first_dts = cur_dts; } else if (sti->cur_dts != RELATIVE_TS_BASE) return; @@ -998,7 +997,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, } } - if (pkt->duration > 0 && (si->packet_buffer || si->parse_queue)) + if (pkt->duration > 0 && (si->packet_buffer.head || si->parse_queue.head)) update_initial_durations(s, st, pkt->stream_index, pkt->duration); /* Correct timestamps with byte offset if demuxers only have timestamps @@ -1195,7 +1194,6 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, compute_pkt_fields(s, st, sti->parser, out_pkt, next_dts, next_pts); ret = avpriv_packet_list_put(&si->parse_queue, - &si->parse_queue_end, out_pkt, NULL, 0); if (ret < 0) goto fail; @@ -1225,7 +1223,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) int ret, got_packet = 0; AVDictionary *metadata = NULL; - while (!got_packet && !si->parse_queue) { + while (!got_packet && !si->parse_queue.head) { AVStream *st; FFStream *sti; @@ -1338,8 +1336,8 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) } } - if (!got_packet && si->parse_queue) - ret = avpriv_packet_list_get(&si->parse_queue, &si->parse_queue_end, pkt); + if (!got_packet && si->parse_queue.head) + ret = avpriv_packet_list_get(&si->parse_queue, pkt); if (ret >= 0) { AVStream *const st = s->streams[pkt->stream_index]; @@ -1420,9 +1418,8 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) AVStream *st; if (!genpts) { - ret = si->packet_buffer - ? avpriv_packet_list_get(&si->packet_buffer, - &si->packet_buffer_end, pkt) + ret = si->packet_buffer.head + ? avpriv_packet_list_get(&si->packet_buffer, pkt) : read_frame_internal(s, pkt); if (ret < 0) return ret; @@ -1430,7 +1427,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) } for (;;) { - PacketList *pktl = si->packet_buffer; + PacketListEntry *pktl = si->packet_buffer.head; if (pktl) { AVPacket *next_pkt = &pktl->pkt; @@ -1463,15 +1460,14 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) // 3. the packets for this stream at the end of the files had valid dts. next_pkt->pts = last_dts + next_pkt->duration; } - pktl = si->packet_buffer; + pktl = si->packet_buffer.head; } /* read packet from packet buffer, if there is data */ st = s->streams[next_pkt->stream_index]; if (!(next_pkt->pts == AV_NOPTS_VALUE && st->discard < AVDISCARD_ALL && next_pkt->dts != AV_NOPTS_VALUE && !eof)) { - ret = avpriv_packet_list_get(&si->packet_buffer, - &si->packet_buffer_end, pkt); + ret = avpriv_packet_list_get(&si->packet_buffer, pkt); goto return_packet; } } @@ -1486,7 +1482,6 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) } ret = avpriv_packet_list_put(&si->packet_buffer, - &si->packet_buffer_end, pkt, NULL, 0); if (ret < 0) { av_packet_unref(pkt); @@ -2598,12 +2593,11 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (!(ic->flags & AVFMT_FLAG_NOBUFFER)) { ret = avpriv_packet_list_put(&si->packet_buffer, - &si->packet_buffer_end, pkt1, NULL, 0); if (ret < 0) goto unref_then_goto_end; - pkt = &si->packet_buffer_end->pkt; + pkt = &si->packet_buffer.tail->pkt; } else { pkt = pkt1; } @@ -2751,8 +2745,8 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) // EOF already reached while reading the stream above. // So continue with reoordering DTS with whatever delay we have. - if (si->packet_buffer && !has_decode_delay_been_guessed(st)) { - update_dts_from_pts(ic, stream_index, si->packet_buffer); + if (si->packet_buffer.head && !has_decode_delay_been_guessed(st)) { + update_dts_from_pts(ic, stream_index, si->packet_buffer.head); } } } diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index e8f043729e..b267197ccc 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -40,7 +40,7 @@ typedef struct FlacMuxerContext { int audio_stream_idx; int waiting_pics; /* audio packets are queued here until we get all the attached pictures */ - PacketList *queue, *queue_end; + PacketList queue; /* updated streaminfo sent by the encoder at the end */ uint8_t streaminfo[FLAC_STREAMINFO_SIZE]; @@ -306,8 +306,8 @@ static int flac_queue_flush(AVFormatContext *s) if (ret < 0) write = 0; - while (c->queue) { - avpriv_packet_list_get(&c->queue, &c->queue_end, pkt); + while (c->queue.head) { + avpriv_packet_list_get(&c->queue, pkt); if (write && (ret = flac_write_audio_packet(s, pkt)) < 0) write = 0; av_packet_unref(pkt); @@ -347,7 +347,7 @@ static void flac_deinit(struct AVFormatContext *s) { FlacMuxerContext *c = s->priv_data; - avpriv_packet_list_free(&c->queue, &c->queue_end); + avpriv_packet_list_free(&c->queue); for (unsigned i = 0; i < s->nb_streams; i++) av_packet_free((AVPacket **)&s->streams[i]->priv_data); } @@ -360,7 +360,7 @@ static int flac_write_packet(struct AVFormatContext *s, AVPacket *pkt) if (pkt->stream_index == c->audio_stream_idx) { if (c->waiting_pics) { /* buffer audio packets until we get all the pictures */ - ret = avpriv_packet_list_put(&c->queue, &c->queue_end, pkt, NULL, 0); + ret = avpriv_packet_list_put(&c->queue, pkt, NULL, 0); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Out of memory in packet queue; skipping attached pictures\n"); c->waiting_pics = 0; diff --git a/libavformat/internal.h b/libavformat/internal.h index 63235ce5cf..bffb8e66ff 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -25,6 +25,7 @@ #include "libavcodec/avcodec.h" #include "libavcodec/bsf.h" +#include "libavcodec/packet_internal.h" #include "avformat.h" #include "os_support.h" @@ -92,8 +93,7 @@ typedef struct FFFormatContext { * not decoded, for example to get the codec parameters in MPEG * streams. */ - struct PacketList *packet_buffer; - struct PacketList *packet_buffer_end; + PacketList packet_buffer; /* av_seek_frame() support */ int64_t data_offset; /**< offset of the first packet */ @@ -104,13 +104,11 @@ typedef struct FFFormatContext { * be identified, as parsing cannot be done without knowing the * codec. */ - struct PacketList *raw_packet_buffer; - struct PacketList *raw_packet_buffer_end; + PacketList raw_packet_buffer; /** * Packets split by the parser get queued here. */ - struct PacketList *parse_queue; - struct PacketList *parse_queue_end; + PacketList parse_queue; /** * The generic code uses this as a temporary packet * to parse packets or for muxing, especially flushing. @@ -393,7 +391,7 @@ typedef struct FFStream { /** * last packet in packet_buffer for this stream when muxing. */ - struct PacketList *last_in_packet_buffer; + PacketListEntry *last_in_packet_buffer; int64_t last_IP_pts; int last_IP_duration; diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index e271916bf1..78e5a4a203 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -396,8 +396,7 @@ typedef struct MatroskaDemuxContext { AVPacket *pkt; /* the packet queue */ - PacketList *queue; - PacketList *queue_end; + PacketList queue; int done; @@ -3112,11 +3111,11 @@ static int matroska_read_header(AVFormatContext *s) static int matroska_deliver_packet(MatroskaDemuxContext *matroska, AVPacket *pkt) { - if (matroska->queue) { + if (matroska->queue.head) { MatroskaTrack *tracks = matroska->tracks.elem; MatroskaTrack *track; - avpriv_packet_list_get(&matroska->queue, &matroska->queue_end, pkt); + avpriv_packet_list_get(&matroska->queue, pkt); track = &tracks[pkt->stream_index]; if (track->has_palette) { uint8_t *pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); @@ -3138,7 +3137,7 @@ static int matroska_deliver_packet(MatroskaDemuxContext *matroska, */ static void matroska_clear_queue(MatroskaDemuxContext *matroska) { - avpriv_packet_list_free(&matroska->queue, &matroska->queue_end); + avpriv_packet_list_free(&matroska->queue); } static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, @@ -3304,7 +3303,7 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, track->audio.buf_timecode = AV_NOPTS_VALUE; pkt->pos = pos; pkt->stream_index = st->index; - ret = avpriv_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, NULL, 0); + ret = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); if (ret < 0) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -3526,7 +3525,7 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, pkt->duration = duration; pkt->pos = pos; - err = avpriv_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, NULL, 0); + err = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); if (err < 0) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -3628,7 +3627,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, pkt->pos = pos; pkt->duration = lace_duration; - res = avpriv_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, NULL, 0); + res = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); if (res < 0) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -4030,10 +4029,10 @@ static int webm_clusters_start_with_keyframe(AVFormatContext *s) matroska_reset_status(matroska, 0, cluster_pos); matroska_clear_queue(matroska); if (matroska_parse_cluster(matroska) < 0 || - !matroska->queue) { + !matroska->queue.head) { break; } - pkt = &matroska->queue->pkt; + pkt = &matroska->queue.head->pkt; // 4 + read is the length of the cluster id and the cluster length field. cluster_pos += 4 + read + cluster_length; if (!(pkt->flags & AV_PKT_FLAG_KEY)) { diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 5d4429b82e..ab33371296 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -5339,7 +5339,7 @@ static int mov_write_squashed_packet(AVFormatContext *s, MOVTrack *track) switch (track->st->codecpar->codec_id) { case AV_CODEC_ID_TTML: { - int had_packets = !!track->squashed_packet_queue; + int had_packets = !!track->squashed_packet_queue.head; if ((ret = ff_mov_generate_squashed_ttml_packet(s, track, squashed_packet)) < 0) { goto finish_squash; @@ -6190,7 +6190,6 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) /* The following will reset pkt and is only allowed to be used * because we return immediately. afterwards. */ if ((ret = avpriv_packet_list_put(&trk->squashed_packet_queue, - &trk->squashed_packet_queue_end, pkt, NULL, 0)) < 0) { return ret; } @@ -6478,8 +6477,7 @@ static void mov_free(AVFormatContext *s) ff_mov_cenc_free(&track->cenc); ffio_free_dyn_buf(&track->mdat_buf); - avpriv_packet_list_free(&track->squashed_packet_queue, - &track->squashed_packet_queue_end); + avpriv_packet_list_free(&track->squashed_packet_queue); } av_freep(&mov->tracks); diff --git a/libavformat/movenc.h b/libavformat/movenc.h index 40077b1afe..2ac84ed070 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -167,7 +167,7 @@ typedef struct MOVTrack { unsigned int squash_fragment_samples_to_one; //< flag to note formats where all samples for a fragment are to be squashed - PacketList *squashed_packet_queue, *squashed_packet_queue_end; + PacketList squashed_packet_queue; } MOVTrack; typedef enum { diff --git a/libavformat/movenc_ttml.c b/libavformat/movenc_ttml.c index 472572b45a..6deae49657 100644 --- a/libavformat/movenc_ttml.c +++ b/libavformat/movenc_ttml.c @@ -70,9 +70,7 @@ static int mov_write_ttml_document_from_queue(AVFormatContext *s, return ret; } - while (!avpriv_packet_list_get(&track->squashed_packet_queue, - &track->squashed_packet_queue_end, - pkt)) { + while (!avpriv_packet_list_get(&track->squashed_packet_queue, pkt)) { end_ts = FFMAX(end_ts, pkt->pts + pkt->duration); // in case of the 'dfxp' muxing mode, each written document is offset @@ -121,7 +119,7 @@ int ff_mov_generate_squashed_ttml_packet(AVFormatContext *s, goto cleanup; } - if (!track->squashed_packet_queue) { + if (!track->squashed_packet_queue.head) { // empty queue, write minimal empty document with zero duration avio_write(ttml_ctx->pb, empty_ttml_document, sizeof(empty_ttml_document) - 1); diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index 0ffc79c025..3ff19da274 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -132,7 +132,7 @@ typedef struct MP3Context { int pics_to_write; /* audio packets are queued here until we get all the attached pictures */ - PacketList *queue, *queue_end; + PacketList queue; } MP3Context; static const uint8_t xing_offtbl[2][2] = {{32, 17}, {17, 9}}; @@ -387,8 +387,8 @@ static int mp3_queue_flush(AVFormatContext *s) ff_id3v2_finish(&mp3->id3, s->pb, s->metadata_header_padding); mp3_write_xing(s); - while (mp3->queue) { - avpriv_packet_list_get(&mp3->queue, &mp3->queue_end, pkt); + while (mp3->queue.head) { + avpriv_packet_list_get(&mp3->queue, pkt); if (write && (ret = mp3_write_audio_packet(s, pkt)) < 0) write = 0; av_packet_unref(pkt); @@ -524,8 +524,7 @@ static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt) if (pkt->stream_index == mp3->audio_stream_idx) { if (mp3->pics_to_write) { /* buffer audio packets until we get all the pictures */ - int ret = avpriv_packet_list_put(&mp3->queue, &mp3->queue_end, - pkt, NULL, 0); + int ret = avpriv_packet_list_put(&mp3->queue, pkt, NULL, 0); if (ret < 0) { av_log(s, AV_LOG_WARNING, "Not enough memory to buffer audio. Skipping picture streams\n"); @@ -633,7 +632,7 @@ static void mp3_deinit(struct AVFormatContext *s) { MP3Context *mp3 = s->priv_data; - avpriv_packet_list_free(&mp3->queue, &mp3->queue_end); + avpriv_packet_list_free(&mp3->queue); av_freep(&mp3->xing_frame); } diff --git a/libavformat/mux.c b/libavformat/mux.c index 0500f636de..c387f8ec6e 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -809,12 +809,12 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, { int ret; FFFormatContext *const si = ffformatcontext(s); - PacketList **next_point, *this_pktl; + PacketListEntry **next_point, *this_pktl; AVStream *st = s->streams[pkt->stream_index]; FFStream *const sti = ffstream(st); int chunked = s->max_chunk_size || s->max_chunk_duration; - this_pktl = av_malloc(sizeof(PacketList)); + this_pktl = av_malloc(sizeof(*this_pktl)); if (!this_pktl) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -831,7 +831,7 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, if (sti->last_in_packet_buffer) { next_point = &(sti->last_in_packet_buffer->next); } else { - next_point = &si->packet_buffer; + next_point = &si->packet_buffer.head; } if (chunked) { @@ -855,7 +855,7 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, if (chunked && !(pkt->flags & CHUNK_START)) goto next_non_null; - if (compare(s, &si->packet_buffer_end->pkt, pkt)) { + if (compare(s, &si->packet_buffer.tail->pkt, pkt)) { while ( *next_point && ((chunked && !((*next_point)->pkt.flags&CHUNK_START)) || !compare(s, &(*next_point)->pkt, pkt))) @@ -863,12 +863,12 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, if (*next_point) goto next_non_null; } else { - next_point = &(si->packet_buffer_end->next); + next_point = &(si->packet_buffer.tail->next); } } av_assert1(!*next_point); - si->packet_buffer_end = this_pktl; + si->packet_buffer.tail = this_pktl; next_non_null: this_pktl->next = *next_point; @@ -939,11 +939,11 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, flush = 1; if (s->max_interleave_delta > 0 && - si->packet_buffer && + si->packet_buffer.head && !flush && si->nb_interleaved_streams == stream_count+noninterleaved_count ) { - AVPacket *const top_pkt = &si->packet_buffer->pkt; + AVPacket *const top_pkt = &si->packet_buffer.head->pkt; int64_t delta_dts = INT64_MIN; int64_t top_dts = av_rescale_q(top_pkt->dts, s->streams[top_pkt->stream_index]->time_base, @@ -952,7 +952,7 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, for (unsigned i = 0; i < s->nb_streams; i++) { const AVStream *const st = s->streams[i]; const FFStream *const sti = cffstream(st); - const PacketList *last = sti->last_in_packet_buffer; + const PacketListEntry *const last = sti->last_in_packet_buffer; int64_t last_dts; if (!last) @@ -973,11 +973,11 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, } } - if (si->packet_buffer && + if (si->packet_buffer.head && eof && (s->flags & AVFMT_FLAG_SHORTEST) && si->shortest_end == AV_NOPTS_VALUE) { - AVPacket *const top_pkt = &si->packet_buffer->pkt; + AVPacket *const top_pkt = &si->packet_buffer.head->pkt; si->shortest_end = av_rescale_q(top_pkt->dts, s->streams[top_pkt->stream_index]->time_base, @@ -985,8 +985,8 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, } if (si->shortest_end != AV_NOPTS_VALUE) { - while (si->packet_buffer) { - PacketList *pktl = si->packet_buffer; + while (si->packet_buffer.head) { + PacketListEntry *pktl = si->packet_buffer.head; AVPacket *const top_pkt = &pktl->pkt; AVStream *const st = s->streams[top_pkt->stream_index]; FFStream *const sti = ffstream(st); @@ -996,9 +996,9 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, if (si->shortest_end + 1 >= top_dts) break; - si->packet_buffer = pktl->next; - if (!si->packet_buffer) - si->packet_buffer_end = NULL; + si->packet_buffer.head = pktl->next; + if (!si->packet_buffer.head) + si->packet_buffer.tail = NULL; if (sti->last_in_packet_buffer == pktl) sti->last_in_packet_buffer = NULL; @@ -1010,13 +1010,13 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, } if (stream_count && flush) { - PacketList *pktl = si->packet_buffer; + PacketListEntry *pktl = si->packet_buffer.head; AVStream *const st = s->streams[pktl->pkt.stream_index]; FFStream *const sti = ffstream(st); if (sti->last_in_packet_buffer == pktl) sti->last_in_packet_buffer = NULL; - avpriv_packet_list_get(&si->packet_buffer, &si->packet_buffer_end, pkt); + avpriv_packet_list_get(&si->packet_buffer, pkt); return 1; } else { @@ -1049,7 +1049,7 @@ int ff_get_muxer_ts_offset(AVFormatContext *s, int stream_index, int64_t *offset const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream) { FFFormatContext *const si = ffformatcontext(s); - PacketList *pktl = si->packet_buffer; + PacketListEntry *pktl = si->packet_buffer.head; while (pktl) { if (pktl->pkt.stream_index == stream) { return &pktl->pkt; diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 4c02e3e264..5e068c8220 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -3097,9 +3097,9 @@ static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flus stream_count += !!ffstream(s->streams[i])->last_in_packet_buffer; if (stream_count && (s->nb_streams == stream_count || flush)) { - PacketList *pktl = si->packet_buffer; + PacketListEntry *pktl = si->packet_buffer.head; if (s->nb_streams != stream_count) { - PacketList *last = NULL; + PacketListEntry *last = NULL; // find last packet in edit unit while (pktl) { if (!stream_count || pktl->pkt.stream_index == 0) @@ -3113,7 +3113,7 @@ static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flus } // purge packet queue while (pktl) { - PacketList *next = pktl->next; + PacketListEntry *next = pktl->next; av_packet_unref(&pktl->pkt); av_freep(&pktl); pktl = next; @@ -3121,16 +3121,16 @@ static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flus if (last) last->next = NULL; else { - si->packet_buffer = NULL; - si->packet_buffer_end = NULL; + si->packet_buffer.head = NULL; + si->packet_buffer.tail = NULL; goto out; } - pktl = si->packet_buffer; + pktl = si->packet_buffer.head; } if (ffstream(s->streams[pktl->pkt.stream_index])->last_in_packet_buffer == pktl) ffstream(s->streams[pktl->pkt.stream_index])->last_in_packet_buffer = NULL; - avpriv_packet_list_get(&si->packet_buffer, &si->packet_buffer_end, out); + avpriv_packet_list_get(&si->packet_buffer, out); av_log(s, AV_LOG_TRACE, "out st:%d dts:%"PRId64"\n", out->stream_index, out->dts); return 1; } else { diff --git a/libavformat/ttaenc.c b/libavformat/ttaenc.c index 5f21fdc144..486f8bdd10 100644 --- a/libavformat/ttaenc.c +++ b/libavformat/ttaenc.c @@ -30,7 +30,7 @@ typedef struct TTAMuxContext { AVIOContext *seek_table; - PacketList *queue, *queue_end; + PacketList queue; uint32_t nb_samples; int frame_size; int last_frame; @@ -94,12 +94,11 @@ static int tta_write_packet(AVFormatContext *s, AVPacket *pkt) TTAMuxContext *tta = s->priv_data; int ret; - ret = avpriv_packet_list_put(&tta->queue, &tta->queue_end, pkt, - NULL, 0); + ret = avpriv_packet_list_put(&tta->queue, pkt, NULL, 0); if (ret < 0) { return ret; } - pkt = &tta->queue_end->pkt; + pkt = &tta->queue.tail->pkt; avio_wl32(tta->seek_table, pkt->size); tta->nb_samples += pkt->duration; @@ -126,8 +125,8 @@ static void tta_queue_flush(AVFormatContext *s) TTAMuxContext *tta = s->priv_data; AVPacket *const pkt = ffformatcontext(s)->pkt; - while (tta->queue) { - avpriv_packet_list_get(&tta->queue, &tta->queue_end, pkt); + while (tta->queue.head) { + avpriv_packet_list_get(&tta->queue, pkt); avio_write(s->pb, pkt->data, pkt->size); av_packet_unref(pkt); } @@ -163,7 +162,7 @@ static void tta_deinit(AVFormatContext *s) TTAMuxContext *tta = s->priv_data; ffio_free_dyn_buf(&tta->seek_table); - avpriv_packet_list_free(&tta->queue, &tta->queue_end); + avpriv_packet_list_free(&tta->queue); } const AVOutputFormat ff_tta_muxer = { diff --git a/libavformat/utils.c b/libavformat/utils.c index ca6185b5c3..e643821fc9 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -239,7 +239,6 @@ int avformat_queue_attached_pictures(AVFormatContext *s) } ret = avpriv_packet_list_put(&si->raw_packet_buffer, - &si->raw_packet_buffer_end, &s->streams[i]->attached_pic, av_packet_ref, 0); if (ret < 0) @@ -300,9 +299,9 @@ int ff_is_intra_only(enum AVCodecID id) void ff_flush_packet_queue(AVFormatContext *s) { FFFormatContext *const si = ffformatcontext(s); - avpriv_packet_list_free(&si->parse_queue, &si->parse_queue_end); - avpriv_packet_list_free(&si->packet_buffer, &si->packet_buffer_end); - avpriv_packet_list_free(&si->raw_packet_buffer, &si->raw_packet_buffer_end); + avpriv_packet_list_free(&si->parse_queue); + avpriv_packet_list_free(&si->packet_buffer); + avpriv_packet_list_free(&si->raw_packet_buffer); si->raw_packet_buffer_size = 0; } From c512be9a908204d9ac99556b908140b10a2dc13e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Tue, 4 Jan 2022 13:40:03 +0100 Subject: [PATCH 38/38] lib*/version.h: Bump Versions before release/5.0 branch Signed-off-by: Andreas Rheinhardt --- libavcodec/version.h | 2 +- libavdevice/version.h | 2 +- libavfilter/version.h | 2 +- libavformat/version.h | 2 +- libavutil/version.h | 2 +- libpostproc/version.h | 2 +- libswresample/version.h | 2 +- libswscale/version.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 7a8852bf15..4d77431842 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 59 -#define LIBAVCODEC_VERSION_MINOR 17 +#define LIBAVCODEC_VERSION_MINOR 18 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavdevice/version.h b/libavdevice/version.h index add4d4228a..75e3378117 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 3 +#define LIBAVDEVICE_VERSION_MINOR 4 #define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ diff --git a/libavfilter/version.h b/libavfilter/version.h index c76f6d22e2..1a1d7ee1cc 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 23 +#define LIBAVFILTER_VERSION_MINOR 24 #define LIBAVFILTER_VERSION_MICRO 100 diff --git a/libavformat/version.h b/libavformat/version.h index e8873c8925..c53d9a6444 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 15 +#define LIBAVFORMAT_VERSION_MINOR 16 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavutil/version.h b/libavutil/version.h index d257e5438d..58c617975d 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 16 +#define LIBAVUTIL_VERSION_MINOR 17 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libpostproc/version.h b/libpostproc/version.h index 33fd0479b1..0c8db478de 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBPOSTPROC_VERSION_MAJOR 56 -#define LIBPOSTPROC_VERSION_MINOR 2 +#define LIBPOSTPROC_VERSION_MINOR 3 #define LIBPOSTPROC_VERSION_MICRO 100 #define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \ diff --git a/libswresample/version.h b/libswresample/version.h index 1a786c6a1d..d6fb8c3e24 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBSWRESAMPLE_VERSION_MAJOR 4 -#define LIBSWRESAMPLE_VERSION_MINOR 2 +#define LIBSWRESAMPLE_VERSION_MINOR 3 #define LIBSWRESAMPLE_VERSION_MICRO 100 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ diff --git a/libswscale/version.h b/libswscale/version.h index aaaf6edc32..24448248e5 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -27,7 +27,7 @@ #include "libavutil/version.h" #define LIBSWSCALE_VERSION_MAJOR 6 -#define LIBSWSCALE_VERSION_MINOR 3 +#define LIBSWSCALE_VERSION_MINOR 4 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \