Home | History | Annotate | Download | only in common
      1 // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style license
      4 // that can be found in the LICENSE file in the root of the source
      5 // tree. An additional intellectual property rights grant can be found
      6 // in the file PATENTS.  All contributing project authors may
      7 // be found in the AUTHORS file in the root of the source tree.
      8 #include "hdr_util.h"
      9 
     10 #include <climits>
     11 #include <cstddef>
     12 #include <new>
     13 
     14 #include "mkvparser/mkvparser.h"
     15 
     16 namespace libwebm {
     17 const int Vp9CodecFeatures::kValueNotPresent = INT_MAX;
     18 
     19 bool CopyPrimaryChromaticity(const mkvparser::PrimaryChromaticity& parser_pc,
     20                              PrimaryChromaticityPtr* muxer_pc) {
     21   muxer_pc->reset(new (std::nothrow)
     22                       mkvmuxer::PrimaryChromaticity(parser_pc.x, parser_pc.y));
     23   if (!muxer_pc->get())
     24     return false;
     25   return true;
     26 }
     27 
     28 bool MasteringMetadataValuePresent(double value) {
     29   return value != mkvparser::MasteringMetadata::kValueNotPresent;
     30 }
     31 
     32 bool CopyMasteringMetadata(const mkvparser::MasteringMetadata& parser_mm,
     33                            mkvmuxer::MasteringMetadata* muxer_mm) {
     34   if (MasteringMetadataValuePresent(parser_mm.luminance_max))
     35     muxer_mm->set_luminance_max(parser_mm.luminance_max);
     36   if (MasteringMetadataValuePresent(parser_mm.luminance_min))
     37     muxer_mm->set_luminance_min(parser_mm.luminance_min);
     38 
     39   PrimaryChromaticityPtr r_ptr(NULL);
     40   PrimaryChromaticityPtr g_ptr(NULL);
     41   PrimaryChromaticityPtr b_ptr(NULL);
     42   PrimaryChromaticityPtr wp_ptr(NULL);
     43 
     44   if (parser_mm.r) {
     45     if (!CopyPrimaryChromaticity(*parser_mm.r, &r_ptr))
     46       return false;
     47   }
     48   if (parser_mm.g) {
     49     if (!CopyPrimaryChromaticity(*parser_mm.g, &g_ptr))
     50       return false;
     51   }
     52   if (parser_mm.b) {
     53     if (!CopyPrimaryChromaticity(*parser_mm.b, &b_ptr))
     54       return false;
     55   }
     56   if (parser_mm.white_point) {
     57     if (!CopyPrimaryChromaticity(*parser_mm.white_point, &wp_ptr))
     58       return false;
     59   }
     60 
     61   if (!muxer_mm->SetChromaticity(r_ptr.get(), g_ptr.get(), b_ptr.get(),
     62                                  wp_ptr.get())) {
     63     return false;
     64   }
     65 
     66   return true;
     67 }
     68 
     69 bool ColourValuePresent(long long value) {
     70   return value != mkvparser::Colour::kValueNotPresent;
     71 }
     72 
     73 bool CopyColour(const mkvparser::Colour& parser_colour,
     74                 mkvmuxer::Colour* muxer_colour) {
     75   if (!muxer_colour)
     76     return false;
     77 
     78   if (ColourValuePresent(parser_colour.matrix_coefficients))
     79     muxer_colour->set_matrix_coefficients(parser_colour.matrix_coefficients);
     80   if (ColourValuePresent(parser_colour.bits_per_channel))
     81     muxer_colour->set_bits_per_channel(parser_colour.bits_per_channel);
     82   if (ColourValuePresent(parser_colour.chroma_subsampling_horz)) {
     83     muxer_colour->set_chroma_subsampling_horz(
     84         parser_colour.chroma_subsampling_horz);
     85   }
     86   if (ColourValuePresent(parser_colour.chroma_subsampling_vert)) {
     87     muxer_colour->set_chroma_subsampling_vert(
     88         parser_colour.chroma_subsampling_vert);
     89   }
     90   if (ColourValuePresent(parser_colour.cb_subsampling_horz))
     91     muxer_colour->set_cb_subsampling_horz(parser_colour.cb_subsampling_horz);
     92   if (ColourValuePresent(parser_colour.cb_subsampling_vert))
     93     muxer_colour->set_cb_subsampling_vert(parser_colour.cb_subsampling_vert);
     94   if (ColourValuePresent(parser_colour.chroma_siting_horz))
     95     muxer_colour->set_chroma_siting_horz(parser_colour.chroma_siting_horz);
     96   if (ColourValuePresent(parser_colour.chroma_siting_vert))
     97     muxer_colour->set_chroma_siting_vert(parser_colour.chroma_siting_vert);
     98   if (ColourValuePresent(parser_colour.range))
     99     muxer_colour->set_range(parser_colour.range);
    100   if (ColourValuePresent(parser_colour.transfer_characteristics)) {
    101     muxer_colour->set_transfer_characteristics(
    102         parser_colour.transfer_characteristics);
    103   }
    104   if (ColourValuePresent(parser_colour.primaries))
    105     muxer_colour->set_primaries(parser_colour.primaries);
    106   if (ColourValuePresent(parser_colour.max_cll))
    107     muxer_colour->set_max_cll(parser_colour.max_cll);
    108   if (ColourValuePresent(parser_colour.max_fall))
    109     muxer_colour->set_max_fall(parser_colour.max_fall);
    110 
    111   if (parser_colour.mastering_metadata) {
    112     mkvmuxer::MasteringMetadata muxer_mm;
    113     if (!CopyMasteringMetadata(*parser_colour.mastering_metadata, &muxer_mm))
    114       return false;
    115     if (!muxer_colour->SetMasteringMetadata(muxer_mm))
    116       return false;
    117   }
    118   return true;
    119 }
    120 
    121 // Format of VPx private data:
    122 //
    123 //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    124 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    125 //  |    ID Byte    |   Length      |                               |
    126 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
    127 //  |                                                               |
    128 //  :               Bytes 1..Length of Codec Feature                :
    129 //  |                                                               |
    130 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    131 //
    132 // ID Byte Format
    133 // ID byte is an unsigned byte.
    134 //   0 1 2 3 4 5 6 7
    135 //  +-+-+-+-+-+-+-+-+
    136 //  |X|    ID       |
    137 //  +-+-+-+-+-+-+-+-+
    138 //
    139 // The X bit is reserved.
    140 //
    141 // See the following link for more information:
    142 // http://www.webmproject.org/vp9/profiles/
    143 bool ParseVpxCodecPrivate(const uint8_t* private_data, int32_t length,
    144                           Vp9CodecFeatures* features) {
    145   const int kVpxCodecPrivateMinLength = 3;
    146   if (!private_data || !features || length < kVpxCodecPrivateMinLength)
    147     return false;
    148 
    149   const uint8_t kVp9ProfileId = 1;
    150   const uint8_t kVp9LevelId = 2;
    151   const uint8_t kVp9BitDepthId = 3;
    152   const uint8_t kVp9ChromaSubsamplingId = 4;
    153   const int kVpxFeatureLength = 1;
    154   int offset = 0;
    155 
    156   // Set features to not set.
    157   features->profile = Vp9CodecFeatures::kValueNotPresent;
    158   features->level = Vp9CodecFeatures::kValueNotPresent;
    159   features->bit_depth = Vp9CodecFeatures::kValueNotPresent;
    160   features->chroma_subsampling = Vp9CodecFeatures::kValueNotPresent;
    161   do {
    162     const uint8_t id_byte = private_data[offset++];
    163     const uint8_t length_byte = private_data[offset++];
    164     if (length_byte != kVpxFeatureLength)
    165       return false;
    166     if (id_byte == kVp9ProfileId) {
    167       const int priv_profile = static_cast<int>(private_data[offset++]);
    168       if (priv_profile < 0 || priv_profile > 3)
    169         return false;
    170       if (features->profile != Vp9CodecFeatures::kValueNotPresent &&
    171           features->profile != priv_profile) {
    172         return false;
    173       }
    174       features->profile = priv_profile;
    175     } else if (id_byte == kVp9LevelId) {
    176       const int priv_level = static_cast<int>(private_data[offset++]);
    177 
    178       const int kNumLevels = 14;
    179       const int levels[kNumLevels] = {10, 11, 20, 21, 30, 31, 40,
    180                                       41, 50, 51, 52, 60, 61, 62};
    181 
    182       for (int i = 0; i < kNumLevels; ++i) {
    183         if (priv_level == levels[i]) {
    184           if (features->level != Vp9CodecFeatures::kValueNotPresent &&
    185               features->level != priv_level) {
    186             return false;
    187           }
    188           features->level = priv_level;
    189           break;
    190         }
    191       }
    192       if (features->level == Vp9CodecFeatures::kValueNotPresent)
    193         return false;
    194     } else if (id_byte == kVp9BitDepthId) {
    195       const int priv_profile = static_cast<int>(private_data[offset++]);
    196       if (priv_profile != 8 && priv_profile != 10 && priv_profile != 12)
    197         return false;
    198       if (features->bit_depth != Vp9CodecFeatures::kValueNotPresent &&
    199           features->bit_depth != priv_profile) {
    200         return false;
    201       }
    202       features->bit_depth = priv_profile;
    203     } else if (id_byte == kVp9ChromaSubsamplingId) {
    204       const int priv_profile = static_cast<int>(private_data[offset++]);
    205       if (priv_profile != 0 && priv_profile != 2 && priv_profile != 3)
    206         return false;
    207       if (features->chroma_subsampling != Vp9CodecFeatures::kValueNotPresent &&
    208           features->chroma_subsampling != priv_profile) {
    209         return false;
    210       }
    211       features->chroma_subsampling = priv_profile;
    212     } else {
    213       // Invalid ID.
    214       return false;
    215     }
    216   } while (offset + kVpxCodecPrivateMinLength <= length);
    217 
    218   return true;
    219 }
    220 }  // namespace libwebm
    221