• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "libavcodec/avcodec.h"
25 #include "vpcc.h"
26 
27 enum VPX_CHROMA_SUBSAMPLING
28 {
29     VPX_SUBSAMPLING_420_VERTICAL = 0,
30     VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA = 1,
31     VPX_SUBSAMPLING_422 = 2,
32     VPX_SUBSAMPLING_444 = 3,
33 };
34 
get_vpx_chroma_subsampling(AVFormatContext * s,enum AVPixelFormat pixel_format,enum AVChromaLocation chroma_location)35 static int get_vpx_chroma_subsampling(AVFormatContext *s,
36                                       enum AVPixelFormat pixel_format,
37                                       enum AVChromaLocation chroma_location)
38 {
39     int chroma_w, chroma_h;
40     if (av_pix_fmt_get_chroma_sub_sample(pixel_format, &chroma_w, &chroma_h) == 0) {
41         if (chroma_w == 1 && chroma_h == 1) {
42             return (chroma_location == AVCHROMA_LOC_LEFT)
43                        ? VPX_SUBSAMPLING_420_VERTICAL
44                        : VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA;
45         } else if (chroma_w == 1 && chroma_h == 0) {
46             return VPX_SUBSAMPLING_422;
47         } else if (chroma_w == 0 && chroma_h == 0) {
48             return VPX_SUBSAMPLING_444;
49         }
50     }
51     av_log(s, AV_LOG_ERROR, "Unsupported pixel format (%d)\n", pixel_format);
52     return -1;
53 }
54 
get_bit_depth(AVFormatContext * s,enum AVPixelFormat pixel_format)55 static int get_bit_depth(AVFormatContext *s, enum AVPixelFormat pixel_format)
56 {
57     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pixel_format);
58     if (desc == NULL) {
59         av_log(s, AV_LOG_ERROR, "Unsupported pixel format (%d)\n",
60                pixel_format);
61         return -1;
62     }
63     return desc->comp[0].depth;
64 }
65 
get_vpx_video_full_range_flag(enum AVColorRange color_range)66 static int get_vpx_video_full_range_flag(enum AVColorRange color_range)
67 {
68     return color_range == AVCOL_RANGE_JPEG;
69 }
70 
71 // Find approximate VP9 level based on the Luma's Sample rate and Picture size.
get_vp9_level(AVCodecParameters * par,AVRational * frame_rate)72 static int get_vp9_level(AVCodecParameters *par, AVRational *frame_rate) {
73     int picture_size = par->width * par->height;
74     int64_t sample_rate;
75 
76     // All decisions will be based on picture_size, if frame rate is missing/invalid
77     if (!frame_rate || !frame_rate->den)
78         sample_rate = 0;
79     else
80         sample_rate = ((int64_t)picture_size * frame_rate->num) / frame_rate->den;
81 
82     if (picture_size <= 0) {
83         return 0;
84     } else if (sample_rate <= 829440     && picture_size <= 36864) {
85         return 10;
86     } else if (sample_rate <= 2764800    && picture_size <= 73728) {
87         return 11;
88     } else if (sample_rate <= 4608000    && picture_size <= 122880) {
89         return 20;
90     } else if (sample_rate <= 9216000    && picture_size <= 245760) {
91         return 21;
92     } else if (sample_rate <= 20736000   && picture_size <= 552960) {
93         return 30;
94     } else if (sample_rate <= 36864000   && picture_size <= 983040) {
95         return 31;
96     } else if (sample_rate <= 83558400   && picture_size <= 2228224) {
97         return 40;
98     } else if (sample_rate <= 160432128  && picture_size <= 2228224) {
99         return 41;
100     } else if (sample_rate <= 311951360  && picture_size <= 8912896) {
101         return 50;
102     } else if (sample_rate <= 588251136  && picture_size <= 8912896) {
103         return 51;
104     } else if (sample_rate <= 1176502272 && picture_size <= 8912896) {
105         return 52;
106     } else if (sample_rate <= 1176502272 && picture_size <= 35651584) {
107         return 60;
108     } else if (sample_rate <= 2353004544 && picture_size <= 35651584) {
109         return 61;
110     } else if (sample_rate <= 4706009088 && picture_size <= 35651584) {
111         return 62;
112     } else {
113         return 0;
114     }
115 }
116 
ff_isom_get_vpcc_features(AVFormatContext * s,AVCodecParameters * par,AVRational * frame_rate,VPCC * vpcc)117 int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par,
118                               AVRational *frame_rate, VPCC *vpcc)
119 {
120     int profile = par->profile;
121     int level = par->level == FF_LEVEL_UNKNOWN ?
122         get_vp9_level(par, frame_rate) : par->level;
123     int bit_depth = get_bit_depth(s, par->format);
124     int vpx_chroma_subsampling =
125         get_vpx_chroma_subsampling(s, par->format, par->chroma_location);
126     int vpx_video_full_range_flag =
127         get_vpx_video_full_range_flag(par->color_range);
128 
129     if (bit_depth < 0 || vpx_chroma_subsampling < 0)
130         return AVERROR_INVALIDDATA;
131 
132     if (profile == FF_PROFILE_UNKNOWN) {
133         if (vpx_chroma_subsampling == VPX_SUBSAMPLING_420_VERTICAL ||
134             vpx_chroma_subsampling == VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA) {
135             profile = (bit_depth == 8) ? FF_PROFILE_VP9_0 : FF_PROFILE_VP9_2;
136         } else {
137             profile = (bit_depth == 8) ? FF_PROFILE_VP9_1 : FF_PROFILE_VP9_3;
138         }
139     }
140 
141     vpcc->profile            = profile;
142     vpcc->level              = level;
143     vpcc->bitdepth           = bit_depth;
144     vpcc->chroma_subsampling = vpx_chroma_subsampling;
145     vpcc->full_range_flag    = vpx_video_full_range_flag;
146 
147     return 0;
148 }
149 
ff_isom_write_vpcc(AVFormatContext * s,AVIOContext * pb,AVCodecParameters * par)150 int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb,
151                        AVCodecParameters *par)
152 {
153     VPCC vpcc;
154     int ret;
155 
156     ret = ff_isom_get_vpcc_features(s, par, NULL, &vpcc);
157     if (ret < 0)
158         return ret;
159 
160     avio_w8(pb, vpcc.profile);
161     avio_w8(pb, vpcc.level);
162     avio_w8(pb, (vpcc.bitdepth << 4) | (vpcc.chroma_subsampling << 1) | vpcc.full_range_flag);
163     avio_w8(pb, par->color_primaries);
164     avio_w8(pb, par->color_trc);
165     avio_w8(pb, par->color_space);
166 
167     // vp9 does not have codec initialization data.
168     avio_wb16(pb, 0);
169     return 0;
170 }
171