| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <unordered_map> |
| 6 |
| 7 #include "mojo/services/media/common/cpp/video_packet_layout.h" |
| 8 |
| 9 namespace mojo { |
| 10 namespace media { |
| 11 |
| 12 namespace { |
| 13 |
| 14 static inline size_t RoundUpToAlign(size_t value, size_t alignment) { |
| 15 return ((value + (alignment - 1)) & ~(alignment - 1)); |
| 16 } |
| 17 |
| 18 } // namespace |
| 19 |
| 20 // static |
| 21 const VideoPacketLayout::PixelFormatInfo& VideoPacketLayout::InfoForPixelFormat( |
| 22 PixelFormat pixel_format) { |
| 23 struct Hash { |
| 24 std::size_t operator()(PixelFormat const& pixel_format) const { |
| 25 return static_cast<size_t>(pixel_format); |
| 26 } |
| 27 }; |
| 28 static const std::unordered_map<PixelFormat, PixelFormatInfo, Hash> table = { |
| 29 {PixelFormat::I420, |
| 30 {3, {1, 1, 1}, {Extent(1, 1), Extent(2, 2), Extent(2, 2)}}}, |
| 31 {PixelFormat::YV12, |
| 32 {3, {1, 1, 1}, {Extent(1, 1), Extent(2, 2), Extent(2, 2)}}}, |
| 33 {PixelFormat::YV16, |
| 34 {3, {1, 1, 1}, {Extent(1, 1), Extent(2, 1), Extent(2, 1)}}}, |
| 35 {PixelFormat::YV12A, |
| 36 {4, |
| 37 {1, 1, 1, 1}, |
| 38 {Extent(1, 1), Extent(2, 2), Extent(2, 2), Extent(1, 1)}}}, |
| 39 {PixelFormat::YV24, |
| 40 {3, {1, 1, 1}, {Extent(1, 1), Extent(1, 1), Extent(1, 1)}}}, |
| 41 {PixelFormat::NV12, {2, {1, 2}, {Extent(1, 1), Extent(2, 2)}}}, |
| 42 {PixelFormat::NV21, {2, {1, 2}, {Extent(1, 1), Extent(2, 2)}}}, |
| 43 {PixelFormat::UYVY, {1, {2}, {Extent(1, 1)}}}, |
| 44 {PixelFormat::YUY2, {1, {2}, {Extent(1, 1)}}}, |
| 45 {PixelFormat::ARGB, {1, {4}, {Extent(1, 1)}}}, |
| 46 {PixelFormat::XRGB, {1, {4}, {Extent(1, 1)}}}, |
| 47 {PixelFormat::RGB24, {1, {3}, {Extent(1, 1)}}}, |
| 48 {PixelFormat::RGB32, {1, {4}, {Extent(1, 1)}}}, |
| 49 {PixelFormat::MJPEG, {1, {0}, {Extent(1, 1)}}}, |
| 50 {PixelFormat::MT21, {2, {1, 2}, {Extent(1, 1), Extent(2, 2)}}}}; |
| 51 |
| 52 MOJO_DCHECK(table.find(pixel_format) != table.end()); |
| 53 return table.find(pixel_format)->second; |
| 54 } |
| 55 |
| 56 size_t VideoPacketLayout::PixelFormatInfo::RowCount(size_t plane, |
| 57 size_t height) const { |
| 58 MOJO_DCHECK(plane < plane_count_); |
| 59 const int sample_height = sample_size_for_plane(plane).height(); |
| 60 return RoundUpToAlign(height, sample_height) / sample_height; |
| 61 } |
| 62 |
| 63 size_t VideoPacketLayout::PixelFormatInfo::ColumnCount(size_t plane, |
| 64 size_t width) const { |
| 65 MOJO_DCHECK(plane < plane_count_); |
| 66 const size_t sample_width = sample_size_for_plane(plane).width(); |
| 67 return RoundUpToAlign(width, sample_width) / sample_width; |
| 68 } |
| 69 |
| 70 size_t VideoPacketLayout::PixelFormatInfo::BytesPerRow(size_t plane, |
| 71 size_t width) const { |
| 72 MOJO_DCHECK(plane < plane_count_); |
| 73 return bytes_per_element_for_plane(plane) * ColumnCount(plane, width); |
| 74 } |
| 75 |
| 76 VideoPacketLayout::Extent VideoPacketLayout::PixelFormatInfo::AlignedSize( |
| 77 const Extent& unaligned_size) const { |
| 78 const Extent alignment = CommonAlignment(); |
| 79 const Extent adjusted = |
| 80 Extent(RoundUpToAlign(unaligned_size.width(), alignment.width()), |
| 81 RoundUpToAlign(unaligned_size.height(), alignment.height())); |
| 82 MOJO_DCHECK((adjusted.width() % alignment.width() == 0) && |
| 83 (adjusted.height() % alignment.height() == 0)); |
| 84 return adjusted; |
| 85 } |
| 86 |
| 87 VideoPacketLayout::Extent VideoPacketLayout::PixelFormatInfo::CommonAlignment() |
| 88 const { |
| 89 size_t max_sample_width = 0; |
| 90 size_t max_sample_height = 0; |
| 91 for (size_t plane = 0; plane < plane_count_; ++plane) { |
| 92 const Extent sample_size = sample_size_for_plane(plane); |
| 93 max_sample_width = std::max(max_sample_width, sample_size.width()); |
| 94 max_sample_height = std::max(max_sample_height, sample_size.height()); |
| 95 } |
| 96 return Extent(max_sample_width, max_sample_height); |
| 97 } |
| 98 |
| 99 VideoPacketLayout::VideoPacketLayout() {} |
| 100 |
| 101 VideoPacketLayout::VideoPacketLayout(PixelFormat pixel_format, |
| 102 uint32_t width, |
| 103 uint32_t height, |
| 104 uint32_t coded_width, |
| 105 uint32_t coded_height) |
| 106 : pixel_format_(pixel_format), |
| 107 width_(width), |
| 108 height_(height), |
| 109 coded_width_(coded_width), |
| 110 coded_height_(coded_height) { |
| 111 const PixelFormatInfo& info = GetPixelFormatInfo(); |
| 112 |
| 113 Extent coded_size(coded_width, coded_height); |
| 114 plane_count_ = info.plane_count_; |
| 115 |
| 116 size_ = 0; |
| 117 Extent aligned_size = info.AlignedSize(coded_size); |
| 118 |
| 119 for (size_t plane = 0; plane < plane_count_; ++plane) { |
| 120 // The *2 in alignment for height is because some formats (e.g. h264) |
| 121 // allow interlaced coding, and then the size needs to be a multiple of two |
| 122 // macroblocks (vertically). See avcodec_align_dimensions2. |
| 123 const size_t height = RoundUpToAlign( |
| 124 info.RowCount(plane, aligned_size.height()), kFrameSizeAlignment * 2); |
| 125 line_stride_[plane] = RoundUpToAlign( |
| 126 info.BytesPerRow(plane, aligned_size.width()), kFrameSizeAlignment); |
| 127 plane_offset_[plane] = size_; |
| 128 size_ += height * line_stride_[plane]; |
| 129 } |
| 130 |
| 131 // Adding an extra line due to overreads. See comment in BuildFrameLayout |
| 132 // in services/media/framework/types/video_stream_type.cc. |
| 133 MOJO_DCHECK(static_cast<size_t>(kUPlaneIndex) < plane_count_); |
| 134 size_ += line_stride_[kUPlaneIndex] + kFrameSizePadding; |
| 135 } |
| 136 |
| 137 VideoPacketLayout::~VideoPacketLayout() {} |
| 138 |
| 139 } // namespace media |
| 140 } // namespace mojo |
| OLD | NEW |