Imported Upstream version 6.1
[platform/upstream/ffmpeg.git] / libavformat / dovi_isom.c
1 /*
2  * DOVI ISO Media common code
3  *
4  * Copyright (c) 2020 Vacing Fang <vacingfang@tencent.com>
5  * Copyright (c) 2021 quietvoid
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23
24 #include "libavutil/dovi_meta.h"
25
26 #include "libavcodec/put_bits.h"
27
28 #include "avformat.h"
29 #include "dovi_isom.h"
30
31 int ff_isom_parse_dvcc_dvvc(void *logctx, AVStream *st,
32                             const uint8_t *buf_ptr, uint64_t size)
33 {
34     uint32_t buf;
35     AVDOVIDecoderConfigurationRecord *dovi;
36     size_t dovi_size;
37
38     if (size > (1 << 30) || size < 4)
39         return AVERROR_INVALIDDATA;
40
41     dovi = av_dovi_alloc(&dovi_size);
42     if (!dovi)
43         return AVERROR(ENOMEM);
44
45     dovi->dv_version_major = *buf_ptr++;    // 8 bits
46     dovi->dv_version_minor = *buf_ptr++;    // 8 bits
47
48     buf = *buf_ptr++ << 8;
49     buf |= *buf_ptr++;
50
51     dovi->dv_profile        = (buf >> 9) & 0x7f;    // 7 bits
52     dovi->dv_level          = (buf >> 3) & 0x3f;    // 6 bits
53     dovi->rpu_present_flag  = (buf >> 2) & 0x01;    // 1 bit
54     dovi->el_present_flag   = (buf >> 1) & 0x01;    // 1 bit
55     dovi->bl_present_flag   =  buf       & 0x01;    // 1 bit
56
57     // Has enough remaining data
58     if (size >= 5) {
59         dovi->dv_bl_signal_compatibility_id = ((*buf_ptr++) >> 4) & 0x0f; // 4 bits
60     } else {
61         // 0 stands for None
62         // Dolby Vision V1.2.93 profiles and levels
63         dovi->dv_bl_signal_compatibility_id = 0;
64     }
65
66     if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
67                                  AV_PKT_DATA_DOVI_CONF, (uint8_t *)dovi, dovi_size, 0)) {
68         av_free(dovi);
69         return AVERROR(ENOMEM);
70     }
71
72     av_log(logctx, AV_LOG_TRACE, "DOVI in dvcC/dvvC/dvwC box, version: %d.%d, profile: %d, level: %d, "
73            "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n",
74            dovi->dv_version_major, dovi->dv_version_minor,
75            dovi->dv_profile, dovi->dv_level,
76            dovi->rpu_present_flag,
77            dovi->el_present_flag,
78            dovi->bl_present_flag,
79            dovi->dv_bl_signal_compatibility_id);
80
81     return 0;
82 }
83
84 void ff_isom_put_dvcc_dvvc(void *logctx, uint8_t out[ISOM_DVCC_DVVC_SIZE],
85                            const AVDOVIDecoderConfigurationRecord *dovi)
86 {
87     PutBitContext pb;
88
89     init_put_bits(&pb, out, ISOM_DVCC_DVVC_SIZE);
90
91     put_bits(&pb, 8, dovi->dv_version_major);
92     put_bits(&pb, 8, dovi->dv_version_minor);
93     put_bits(&pb, 7, dovi->dv_profile & 0x7f);
94     put_bits(&pb, 6, dovi->dv_level & 0x3f);
95     put_bits(&pb, 1, !!dovi->rpu_present_flag);
96     put_bits(&pb, 1, !!dovi->el_present_flag);
97     put_bits(&pb, 1, !!dovi->bl_present_flag);
98     put_bits(&pb, 4, dovi->dv_bl_signal_compatibility_id & 0x0f);
99
100     put_bits(&pb, 28, 0); /* reserved */
101     put_bits32(&pb, 0); /* reserved */
102     put_bits32(&pb, 0); /* reserved */
103     put_bits32(&pb, 0); /* reserved */
104     put_bits32(&pb, 0); /* reserved */
105
106     flush_put_bits(&pb);
107
108     av_log(logctx, AV_LOG_DEBUG,
109            "DOVI in %s box, version: %d.%d, profile: %d, level: %d, "
110            "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n",
111            dovi->dv_profile > 10 ? "dvwC" : (dovi->dv_profile > 7 ? "dvvC" : "dvcC"),
112            dovi->dv_version_major, dovi->dv_version_minor,
113            dovi->dv_profile, dovi->dv_level,
114            dovi->rpu_present_flag,
115            dovi->el_present_flag,
116            dovi->bl_present_flag,
117            dovi->dv_bl_signal_compatibility_id);
118 }