[FFmpeg-devel] [PATCH 2/2] avformat/framecrcenc: Make side-data checksums endian-independent
Andriy Gelman
andriy.gelman at gmail.com
Sun Dec 6 19:09:56 EET 2020
On Sun, 06. Dec 04:09, Andreas Rheinhardt wrote:
> Do this by converting big-endian side data to little endian for
> checksumming. Fixes the ts-demux FATE test.
It's quite nicely done imo.
Same as Michael, I enabled ts-demux test in link below and it worked fine (PPC64 qemu)
https://patchwork.ffmpeg.org/project/ffmpeg/patch/20201206030934.395352-2-andreas.rheinhardt@gmail.com/
>
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
> ---
> a) When commenting the #if HAVE_BIGENDIAN out, I get the same checksum
> for the test in [1] as Andriy got on a real BE system; I have not done
> more testing, lacking actual BE hardware. In particular, the claim about
> the ts-demux FATE test is untested.
> b) If side data doesn't have the expected size, then LE and BE might
> still produce different results (but then there must be a bigger problem
> elsewhere).
> c) This code here is designed to work even after the next major version
> bump when the size of some members of AVCPBProperties change. (Of course,
> some FATE checksums will need to be adapted then, but for both LE and BE
> in the same manner.)
>
> libavformat/framecrcenc.c | 61 +++++++++++++++++++++++++++++++++++----
> 1 file changed, 56 insertions(+), 5 deletions(-)
>
> diff --git a/libavformat/framecrcenc.c b/libavformat/framecrcenc.c
> index f7c48779a0..390024dbe8 100644
> --- a/libavformat/framecrcenc.c
> +++ b/libavformat/framecrcenc.c
> @@ -21,9 +21,11 @@
>
> #include <inttypes.h>
>
> +#include "config.h"
> #include "libavutil/adler32.h"
> #include "libavutil/avstring.h"
> #include "libavutil/intreadwrite.h"
> +#include "libavcodec/avcodec.h"
> #include "avformat.h"
> #include "internal.h"
>
> @@ -43,6 +45,19 @@ static int framecrc_write_header(struct AVFormatContext *s)
> return ff_framehash_write_header(s);
> }
>
> +#if HAVE_BIGENDIAN
> +static void inline bswap(char *buf, int offset, int size)
> +{
> + if (size == 8) {
> + uint64_t val = AV_RN64(buf + offset);
> + AV_WN64(buf + offset, av_bswap64(val));
> + } else if (size == 4) {
> + uint32_t val = AV_RN32(buf + offset);
> + AV_WN32(buf + offset, av_bswap32(val));
> + }
Just wondering why you decided this way with av_bswap and not AV_WLx
as in the code below.
> +}
> +#endif
> +
> static int framecrc_write_packet(struct AVFormatContext *s, AVPacket *pkt)
> {
> uint32_t crc = av_adler32_update(0, pkt->data, pkt->size);
> @@ -58,17 +73,53 @@ static int framecrc_write_packet(struct AVFormatContext *s, AVPacket *pkt)
>
> for (i=0; i<pkt->side_data_elems; i++) {
> const AVPacketSideData *const sd = &pkt->side_data[i];
> + const uint8_t *data = sd->data;
> uint32_t side_data_crc = 0;
> - if (HAVE_BIGENDIAN && AV_PKT_DATA_PALETTE == pkt->side_data[i].type) {
> +
> + switch (sd->type) {
> +#if HAVE_BIGENDIAN
> + uint8_t buf[FFMAX(sizeof(AVCPBProperties),
> + sizeof(AVProducerReferenceTime))];
> + case AV_PKT_DATA_PALETTE:
> + case AV_PKT_DATA_REPLAYGAIN:
> + case AV_PKT_DATA_DISPLAYMATRIX:
> + case AV_PKT_DATA_STEREO3D:
> + case AV_PKT_DATA_AUDIO_SERVICE_TYPE:
> + case AV_PKT_DATA_FALLBACK_TRACK:
> + case AV_PKT_DATA_MASTERING_DISPLAY_METADATA:
> + case AV_PKT_DATA_SPHERICAL:
> + case AV_PKT_DATA_CONTENT_LIGHT_LEVEL:
> + case AV_PKT_DATA_S12M_TIMECODE:
> for (int j = 0; j < sd->size / 4; j++) {
> uint8_t buf[4];
> AV_WL32(buf, AV_RB32(sd->data + 4 * j));
> side_data_crc = av_adler32_update(side_data_crc, buf, 4);
> }
> - } else {
> - side_data_crc = av_adler32_update(0,
> - pkt->side_data[i].data,
> - pkt->side_data[i].size);
> + break;
> + case AV_PKT_DATA_CPB_PROPERTIES:
> +#define BSWAP(struct, field) bswap(buf, offsetof(struct, field), sizeof(((struct){0}).field))
> + if (sd->size == sizeof(AVCPBProperties)) {
> + memcpy(buf, sd->data, sizeof(AVCPBProperties));
> + data = buf;
> + BSWAP(AVCPBProperties, max_bitrate);
> + BSWAP(AVCPBProperties, min_bitrate);
> + BSWAP(AVCPBProperties, avg_bitrate);
> + BSWAP(AVCPBProperties, buffer_size);
> + BSWAP(AVCPBProperties, vbv_delay);
> + }
> + goto pod;
> + case AV_PKT_DATA_PRFT:
> + if (sd->size == sizeof(AVProducerReferenceTime)) {
> + memcpy(buf, sd->data, sizeof(AVProducerReferenceTime));
> + data = buf;
> + BSWAP(AVProducerReferenceTime, wallclock);
> + BSWAP(AVProducerReferenceTime, flags);
> + }
> + goto pod;
> + pod:
> +#endif
> + default:
> + side_data_crc = av_adler32_update(0, data, sd->size);
> }
> av_strlcatf(buf, sizeof(buf), ", %8d, 0x%08"PRIx32, pkt->side_data[i].size, side_data_crc);
> }
Btw libavformat/hashenc.c is also doing a conversion on the palette
side data. Do you think that code should be updated?
--
Andriy
More information about the ffmpeg-devel
mailing list