[FFmpeg-cvslog] mov: Export frame packing information from pack box

Vittorio Giovara git at videolan.org
Thu Jul 31 12:24:53 EEST 2025


ffmpeg | branch: master | Vittorio Giovara <vittorio.giovara at gmail.com> | Wed Jul 23 23:29:19 2025 +0200| [c275f3bfa16035b33ba879580512d517d11c6ddd] | committer: Vittorio Giovara

mov: Export frame packing information from pack box

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=c275f3bfa16035b33ba879580512d517d11c6ddd
---

 libavformat/mov.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 5ff9b5ba1b..1c14b6fcf9 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -6594,6 +6594,85 @@ static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     return 0;
 }
 
+static int mov_read_pack(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+    AVStream *st;
+    MOVStreamContext *sc;
+    int size = 0;
+    int64_t remaining;
+    uint32_t tag = 0;
+    enum AVStereo3DType type = AV_STEREO3D_2D;
+
+    if (c->fc->nb_streams < 1)
+        return 0;
+
+    st = c->fc->streams[c->fc->nb_streams - 1];
+    sc = st->priv_data;
+
+    remaining = atom.size;
+    while (remaining > 0) {
+        size = avio_rb32(pb);
+        if (size < 8 || size > remaining ) {
+            av_log(c->fc, AV_LOG_ERROR, "Invalid child size in pack box\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        tag = avio_rl32(pb);
+        switch (tag) {
+        case MKTAG('p','k','i','n'): {
+            if (size != 16) {
+                av_log(c->fc, AV_LOG_ERROR, "Invalid size of pkin box: %d\n", size);
+                return AVERROR_INVALIDDATA;
+            }
+            avio_skip(pb, 1); // version
+            avio_skip(pb, 3); // flags
+
+            tag = avio_rl32(pb);
+            switch (tag) {
+            case MKTAG('s','i','d','e'):
+                type = AV_STEREO3D_SIDEBYSIDE;
+                break;
+            case MKTAG('o','v','e','r'):
+                type = AV_STEREO3D_TOPBOTTOM;
+                break;
+            case 0:
+                // This means value will be set in another layer
+                break;
+            default:
+                av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pkin: 0x%08X\n", tag);
+                avio_skip(pb, size - 8);
+                break;
+            }
+
+            break;
+        }
+        default:
+            av_log(c->fc, AV_LOG_WARNING, "Unknown tag in pack: 0x%08X\n", tag);
+            avio_skip(pb, size - 8);
+            break;
+        }
+        remaining -= size;
+    }
+
+    if (remaining != 0) {
+        av_log(c->fc, AV_LOG_ERROR, "Broken pack box\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    if (type == AV_STEREO3D_2D)
+        return 0;
+
+    if (!sc->stereo3d) {
+        sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
+        if (!sc->stereo3d)
+            return AVERROR(ENOMEM);
+    }
+
+    sc->stereo3d->type = type;
+
+    return 0;
+}
+
 static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
     AVStream *st;
@@ -7005,6 +7084,13 @@ static int mov_read_vexu(MOVContext *c, AVIOContext *pb, MOVAtom atom)
                 return ret;
             break;
         }
+        case MKTAG('p','a','c','k'): {
+            MOVAtom pack = { tag, size - 8 };
+            int ret = mov_read_pack(c, pb, pack);
+            if (ret < 0)
+                return ret;
+            break;
+        }
         default:
             av_log(c->fc, AV_LOG_WARNING, "Unknown tag in vexu: 0x%08X\n", tag);
             avio_skip(pb, size - 8);



More information about the ffmpeg-cvslog mailing list