Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(807)

Side by Side Diff: mojo/services/media/common/cpp/video_converter.cc

Issue 2068043005: Motown: Video renderer library code (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Fix empty packet detection. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "mojo/services/media/common/cpp/video_converter.h"
6
7 namespace mojo {
8 namespace media {
9
10 VideoConverter::VideoConverter() {
11 BuildColorspaceTable();
12 }
13
14 VideoConverter::~VideoConverter() {}
15
16 namespace {
17
18 uint8_t ToByte(float f) {
19 if (f < 0.0f) {
kulakowski 2016/06/17 21:15:40 I'm paranoid having once seen someone spend days d
dalesat 2016/06/18 00:07:08 This isn't terribly critical, being temporary code
20 return 0u;
21 }
22
23 if (f > 255.0f) {
24 return 255u;
25 }
26
27 return static_cast<uint8_t>(f);
28 }
29
30 size_t ColorspaceTableOffset(uint8_t y, uint8_t u, uint8_t v) {
kulakowski 2016/06/17 21:15:40 Why do this math yourself and not write [y][u][v]?
dalesat 2016/06/18 00:07:08 I'm just not familiar with using arrays of arrays
31 return (y << 8u | u) << 8u | v;
32 }
33
34 } // namespace
35
36 void VideoConverter::BuildColorspaceTable() {
37 colorspace_table_.reset(new uint32_t[256 * 256 * 256]);
38
39 uint32_t* p = colorspace_table_.get();
40
41 for (float y = 0.0f; y < 256.0f; y += 1.0f) {
kulakowski 2016/06/17 21:15:40 I hope you typed these constants correctly :) I b
dalesat 2016/06/18 00:07:08 Doing the iteration with ints rather than floats m
42 for (float u = 0.0f; u < 256.0f; u += 1.0f) {
43 for (float v = 0.0f; v < 256.0f; v += 1.0f) {
44 // R = 1.164(Y - 16) + 1.596(V - 128)
45 uint8_t r = ToByte(1.164f * (y - 16.0f) + 1.596f * (v - 128.0f));
46
47 // G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
48 uint8_t g = ToByte(1.164f * (y - 16.0f) - 0.813f * (v - 128.0f) -
49 0.391f * (u - 128.0f));
50
51 // B = 1.164(Y - 16) + 2.018(U - 128)
52 uint8_t b = ToByte(1.164f * (y - 16.0f) + 2.018f * (u - 128.0f));
53
54 *p = r | g << 8u | b << 16u | 255u << 24u;
kulakowski 2016/06/17 21:15:40 I and someone looking over my shoulder both are un
dalesat 2016/06/18 00:07:08 Done.
55 ++p;
56 }
57 }
58 }
59 }
60
61 void VideoConverter::SetMediaType(const MediaTypePtr& media_type) {
62 MOJO_DCHECK(media_type);
63 MOJO_DCHECK(media_type->medium == MediaTypeMedium::VIDEO);
64 MOJO_DCHECK(media_type->encoding == MediaType::kVideoEncodingUncompressed);
65 MOJO_DCHECK(media_type->details);
66
67 const VideoMediaTypeDetailsPtr& details = media_type->details->get_video();
68 MOJO_DCHECK(details);
69 MOJO_DCHECK(details->pixel_format == PixelFormat::YV12)
70 << "only YV12 video conversion is currently implemented";
71
72 layout_ =
73 VideoPacketLayout(details->pixel_format, details->width, details->height,
74 details->coded_width, details->coded_height);
75
76 media_type_set_ = true;
77 }
78
79 void VideoConverter::ConvertFrame(uint8_t* rgba_buffer,
80 uint32_t view_width,
81 uint32_t view_height,
82 void* payload,
83 uint64_t payload_size) {
84 MOJO_DCHECK(rgba_buffer != nullptr);
85 MOJO_DCHECK(view_width != 0);
86 MOJO_DCHECK(view_height != 0);
87 MOJO_DCHECK(payload != nullptr);
88 MOJO_DCHECK(payload_size != 0);
89 MOJO_DCHECK(media_type_set_)
90 << "need to call SetMediaType before ConvertFrame";
91
92 uint32_t height = std::min(layout_.height(), view_height);
93 uint32_t width = std::min(layout_.width(), view_width);
94
95 // YV12 frames have three separate planes. The Y plane has 8-bit Y values for
96 // each pixel. The U and V planes have 8-bit U and V values for 2x2 grids of
97 // pixels, so those planes are each 1/4 the size of the Y plane. Both the
98 // inner and outer loops below are unrolled to deal with the 2x2 logic.
99
100 size_t dest_line_stride = view_width;
101 size_t y_line_stride =
102 layout_.line_stride_for_plane(VideoPacketLayout::kYPlaneIndex);
103 size_t u_line_stride =
104 layout_.line_stride_for_plane(VideoPacketLayout::kUPlaneIndex);
105 size_t v_line_stride =
106 layout_.line_stride_for_plane(VideoPacketLayout::kVPlaneIndex);
107
108 uint32_t* dest_line = reinterpret_cast<uint32_t*>(
109 rgba_buffer + dest_line_stride * (view_height - 1) * sizeof(uint32_t));
110 uint8_t* y_line =
111 reinterpret_cast<uint8_t*>(payload) +
112 layout_.plane_offset_for_plane(VideoPacketLayout::kYPlaneIndex);
113 uint8_t* u_line =
114 reinterpret_cast<uint8_t*>(payload) +
115 layout_.plane_offset_for_plane(VideoPacketLayout::kUPlaneIndex);
116 uint8_t* v_line =
117 reinterpret_cast<uint8_t*>(payload) +
118 layout_.plane_offset_for_plane(VideoPacketLayout::kVPlaneIndex);
119
120 for (uint32_t line = 0; line < height; ++line) {
121 ConvertLine(dest_line, y_line, u_line, v_line, width);
122
123 dest_line -= dest_line_stride;
124 y_line += y_line_stride;
125 // Notice we aren't updating u_line and v_line here.
126
127 // If we hadn't unrolled the loop, it would have ended here.
128 if (++line == height) {
129 break;
130 }
131
132 ConvertLine(dest_line, y_line, u_line, v_line, width);
133
134 dest_line -= dest_line_stride;
135 y_line += y_line_stride;
136 // Here, we ARE updating u_line and v_line, because we've moved vertically
137 // out of the 2x2 grid.
138 u_line += u_line_stride;
139 v_line += v_line_stride;
140 }
141 }
142
143 void VideoConverter::ConvertLine(uint32_t* dest_pixel,
144 uint8_t* y_pixel,
145 uint8_t* u_pixel,
146 uint8_t* v_pixel,
147 uint32_t width) {
148 for (uint32_t pixel = 0; pixel < width; ++pixel) {
149 *dest_pixel =
150 colorspace_table_
151 .get()[ColorspaceTableOffset(*y_pixel, *u_pixel, *v_pixel)];
152 ++dest_pixel;
153 ++y_pixel;
154 // Notice we aren't incrementing u_pixel and v_pixel here.
155
156 // If we hadn't unrolled the loop, it would have ended here.
157 if (++pixel == width) {
158 break;
159 }
160
161 *dest_pixel =
162 colorspace_table_
163 .get()[ColorspaceTableOffset(*y_pixel, *u_pixel, *v_pixel)];
164 ++dest_pixel;
165 ++y_pixel;
166 // Here, we ARE incrementing u_pixel and v_pixel, because we've moved
167 // horizontally out of the 2x2 grid.
168 ++u_pixel;
169 ++v_pixel;
170 }
171 }
172
173 } // namespace media
174 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698