diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index 55b509108e..2ff779720b 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -397,6 +397,7 @@ const char *av_packet_side_data_name(enum AVPacketSideDataType type)
     case AV_PKT_DATA_AFD:                        return "Active Format Description data";
     case AV_PKT_DATA_ICC_PROFILE:                return "ICC Profile";
     case AV_PKT_DATA_DOVI_CONF:                  return "DOVI configuration record";
+    case AV_PKT_DATA_CLEAN_APERTURE:             return "Clean Aperture";
     }
     return NULL;
 }
diff --git a/libavcodec/packet.h b/libavcodec/packet.h
index 41485f4527..a0f8c29a33 100644
--- a/libavcodec/packet.h
+++ b/libavcodec/packet.h
@@ -282,6 +282,18 @@ enum AVPacketSideDataType {
      */
     AV_PKT_DATA_DOVI_CONF,
 
+    /**
+     * This side data contains a crop region (clean aperture) that defines the
+     * region of the stored image that should be cropped.
+     *
+     * It is intended to be used to store crop-related metadata from the
+     * container. For example, the CLAP atom in MOV files, and PixelCrop fields
+     * in MKV.
+     *
+     * The data is of type AVCleanAperture (see libavutil/clean_aperture.h)
+     */
+    AV_PKT_DATA_CLEAN_APERTURE,
+
     /**
      * The number of side data types.
      * This is not part of the public API/ABI in the sense that it may
diff --git a/libavformat/dump.c b/libavformat/dump.c
index 5e9a03185f..060e7b2d10 100644
--- a/libavformat/dump.c
+++ b/libavformat/dump.c
@@ -26,6 +26,7 @@
 #include "libavutil/display.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/log.h"
+#include "libavutil/clean_aperture.h"
 #include "libavutil/mastering_display_metadata.h"
 #include "libavutil/dovi_meta.h"
 #include "libavutil/mathematics.h"
@@ -402,6 +403,16 @@ static void dump_dovi_conf(void *ctx, AVPacketSideData* sd)
            dovi->dv_bl_signal_compatibility_id);
 }
 
+static void dump_clean_aperture(void *ctx, AVPacketSideData *sd)
+{
+    AVCleanAperture *clap = (AVCleanAperture *)sd->data;
+    av_log(ctx, AV_LOG_INFO, "[width %d/%d height:%d/%d h_offset:%d/%d v_offset:%d/%d]",
+           clap->width.num, clap->width.den,
+           clap->height.num, clap->height.den,
+           clap->horizontal_offset.num, clap->horizontal_offset.den,
+           clap->vertical_offset.num, clap->vertical_offset.den);
+}
+
 static void dump_sidedata(void *ctx, AVStream *st, const char *indent)
 {
     int i;
@@ -468,6 +479,10 @@ static void dump_sidedata(void *ctx, AVStream *st, const char *indent)
             av_log(ctx, AV_LOG_INFO, "DOVI configuration record: ");
             dump_dovi_conf(ctx, &sd);
             break;
+        case AV_PKT_DATA_CLEAN_APERTURE:
+            av_log(ctx, AV_LOG_INFO, "Clean aperture:");
+            dump_clean_aperture(ctx, &sd);
+            break;
         default:
             av_log(ctx, AV_LOG_INFO,
                    "unknown side data type %d (%d bytes)", sd.type, sd.size);
diff --git a/libavutil/Makefile b/libavutil/Makefile
index 966eec41aa..e9c9b2bff1 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -17,6 +17,7 @@ HEADERS = adler32.h                                                     \
           cast5.h                                                       \
           camellia.h                                                    \
           channel_layout.h                                              \
+          clean_aperture.h                                              \
           common.h                                                      \
           cpu.h                                                         \
           crc.h                                                         \
@@ -107,6 +108,7 @@ OBJS = adler32.o                                                        \
        cast5.o                                                          \
        camellia.o                                                       \
        channel_layout.o                                                 \
+       clean_aperture.o                                                 \
        color_utils.o                                                    \
        cpu.o                                                            \
        crc.o                                                            \
diff --git a/libavutil/clean_aperture.c b/libavutil/clean_aperture.c
new file mode 100644
index 0000000000..0be51725f3
--- /dev/null
+++ b/libavutil/clean_aperture.c
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2020 Neil Birkbeck <neil.birkbeck@gmail.com>
+ *
+ * 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 <stdint.h>
+#include <string.h>
+
+#include "clean_aperture.h"
+#include "mem.h"
+
+AVCleanAperture *av_clean_aperture_alloc(void)
+{
+    return av_mallocz(sizeof(AVCleanAperture));
+}
diff --git a/libavutil/clean_aperture.h b/libavutil/clean_aperture.h
new file mode 100644
index 0000000000..116cf36976
--- /dev/null
+++ b/libavutil/clean_aperture.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020 Neil Birkbeck <neil.birkbeck@gmail.com>
+ *
+ * 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 AVUTIL_CLEAN_APERTURE_H
+#define AVUTIL_CLEAN_APERTURE_H
+
+#include "frame.h"
+#include "rational.h"
+
+
+/**
+ * Clean aperture represents the subset of stored pixels (as width, height
+ * and a center offset) that relates the pixels of the stored image to a
+ * canonical display area.
+ *
+ * The clean aperture structure is meant to be allocated as stream side data.
+ * It represents the Clean Aperture Atom (CLAP) and container-level cropping
+ * information (e.g., PixelCrop fields in MKV).
+ *
+ * @note The struct should be allocated with av_clean_aperture_alloc()
+ *       and its size is not a part of the public ABI.
+ */
+typedef struct AVCleanAperture {
+    // The width of the aperture window (<= stored image width)
+    AVRational width;
+
+    // The height of the aperture window (<= stored image height)
+    AVRational height;
+
+    // The horizontal offset of the center (relative to stored image center)
+    AVRational horizontal_offset;
+
+    // The vertical offset of the center (relative to stored image center)
+    AVRational vertical_offset;
+} AVCleanAperture;
+
+/**
+ * Allocate an AVCleanAperture structure and set its fields to
+ * default values. The resulting struct can be freed using av_freep().
+ *
+ * @return An AVCleanAperture filled with default values or NULL
+ *         on failure.
+ */
+AVCleanAperture *av_clean_aperture_alloc(void);
+
+#endif /* AVUTIL_CLEAN_APERTURE_H */
