Add experimental support for vp9 in iso-bmff
[ffmpeg.git] / libavformat / vpcc.c
1 /*
2  * Copyright (c) 2016 Google Inc.
3  * Copyright (c) 2016 KongQun Yang (kqyang@google.com)
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "libavutil/pixdesc.h"
23 #include "libavutil/pixfmt.h"
24 #include "vpcc.h"
25
26 enum VpxColorSpace
27 {
28     VPX_COLOR_SPACE_UNSPECIFIED = 0,
29     VPX_COLOR_SPACE_BT601 = 1,
30     VPX_COLOR_SPACE_BT709 = 2,
31     VPX_COLOR_SPACE_SMPTE_170 = 3,
32     VPX_COLOR_SPACE_SMPTE_240 = 4,
33     VPX_COLOR_SPACE_BT2020_NCL = 5,
34     VPX_COLOR_SPACE_BT2020_CL = 6,
35     VPX_COLOR_SPACE_RGB = 7,
36 };
37
38 static int get_vpx_color_space(AVFormatContext *s,
39                                enum AVColorSpace color_space)
40 {
41     switch (color_space) {
42     case AVCOL_SPC_RGB:
43         return VPX_COLOR_SPACE_RGB;
44     case AVCOL_SPC_BT709:
45         return VPX_COLOR_SPACE_BT709;
46     case AVCOL_SPC_UNSPECIFIED:
47         return VPX_COLOR_SPACE_UNSPECIFIED;
48     case AVCOL_SPC_BT470BG:
49         return VPX_COLOR_SPACE_BT601;
50     case AVCOL_SPC_SMPTE170M:
51         return VPX_COLOR_SPACE_SMPTE_170;
52     case AVCOL_SPC_SMPTE240M:
53         return VPX_COLOR_SPACE_SMPTE_240;
54     case AVCOL_SPC_BT2020_NCL:
55         return VPX_COLOR_SPACE_BT2020_NCL;
56     case AVCOL_SPC_BT2020_CL:
57         return VPX_COLOR_SPACE_BT2020_CL;
58     default:
59         av_log(s, AV_LOG_ERROR, "Unsupported color space (%d)\n", color_space);
60         return -1;
61     }
62 }
63
64 enum VPX_CHROMA_SUBSAMPLING
65 {
66     VPX_SUBSAMPLING_420_VERTICAL = 0,
67     VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA = 1,
68     VPX_SUBSAMPLING_422 = 2,
69     VPX_SUBSAMPLING_444 = 3,
70 };
71
72 static int get_vpx_chroma_subsampling(AVFormatContext *s,
73                                       enum AVPixelFormat pixel_format,
74                                       enum AVChromaLocation chroma_location)
75 {
76     int chroma_w, chroma_h;
77     if (av_pix_fmt_get_chroma_sub_sample(pixel_format, &chroma_w, &chroma_h) == 0) {
78         if (chroma_w == 1 && chroma_h == 1) {
79             return (chroma_location == AVCHROMA_LOC_LEFT)
80                        ? VPX_SUBSAMPLING_420_VERTICAL
81                        : VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA;
82         } else if (chroma_w == 1 && chroma_h == 0) {
83             return VPX_SUBSAMPLING_422;
84         } else if (chroma_w == 0 && chroma_h == 0) {
85             return VPX_SUBSAMPLING_444;
86         }
87     }
88     av_log(s, AV_LOG_ERROR, "Unsupported pixel format (%d)\n", pixel_format);
89     return -1;
90 }
91
92 static int get_bit_depth(AVFormatContext *s, enum AVPixelFormat pixel_format)
93 {
94     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pixel_format);
95     if (desc == NULL) {
96         av_log(s, AV_LOG_ERROR, "Unsupported pixel format (%d)\n",
97                pixel_format);
98         return -1;
99     }
100     return desc->comp[0].depth;
101 }
102
103 static int get_vpx_transfer_function(
104     enum AVColorTransferCharacteristic transfer)
105 {
106     return transfer == AVCOL_TRC_SMPTEST2084;
107 }
108
109 static int get_vpx_video_full_range_flag(enum AVColorRange color_range)
110 {
111     return color_range == AVCOL_RANGE_JPEG;
112 }
113
114 int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb,
115                        AVCodecParameters *par)
116 {
117     int profile = par->profile;
118     int level = par->level == FF_LEVEL_UNKNOWN ? 0 : par->level;
119     int bit_depth = get_bit_depth(s, par->format);
120     int vpx_color_space = get_vpx_color_space(s, par->color_space);
121     int vpx_chroma_subsampling =
122         get_vpx_chroma_subsampling(s, par->format, par->chroma_location);
123     int vpx_transfer_function = get_vpx_transfer_function(par->color_trc);
124     int vpx_video_full_range_flag =
125         get_vpx_video_full_range_flag(par->color_range);
126
127     if (bit_depth < 0 || vpx_color_space < 0 || vpx_chroma_subsampling < 0)
128         return AVERROR_INVALIDDATA;
129
130     if (profile == FF_PROFILE_UNKNOWN) {
131         if (vpx_chroma_subsampling == VPX_SUBSAMPLING_420_VERTICAL ||
132             vpx_chroma_subsampling == VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA) {
133             profile = (bit_depth == 8) ? FF_PROFILE_VP9_0 : FF_PROFILE_VP9_2;
134         } else {
135             profile = (bit_depth == 8) ? FF_PROFILE_VP9_1 : FF_PROFILE_VP9_3;
136         }
137     }
138
139     avio_w8(pb, profile);
140     avio_w8(pb, level);
141     avio_w8(pb, (bit_depth << 4) | vpx_color_space);
142     avio_w8(pb, (vpx_chroma_subsampling << 4) | (vpx_transfer_function << 1) |
143                     vpx_video_full_range_flag);
144
145     // vp9 does not have codec initialization data.
146     avio_wb16(pb, 0);
147     return 0;
148 }