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

Side by Side Diff: media/player/view.h

Issue 100075: media player view window for painting frames to the display with YUV conversi... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file.
4
5 // View.h : Paints the current movie frame (with scaling) to the display.
6 // TODO(fbarchard): Consider rewriting as view.cc and view.h
7
8 #ifndef MEDIA_PLAYER_VIEW_H_
9 #define MEDIA_PLAYER_VIEW_H_
10
11 // Enable timing code by turning on TESTING macro.
12 // #define TESTING 1
13
14 #ifdef TESTING
15 #define _CRT_SECURE_NO_WARNINGS
16 #include <windows.h>
17 #include <stdio.h>
18 #include <process.h>
19 #include <string.h>
20 #endif
21
22 #include <atlscrl.h>
23
24 #include "base/basictypes.h"
25 #include "media/base/buffers.h"
26 #include "media/base/factory.h"
27 #include "media/base/filters.h"
28 #include "media/base/yuv_convert.h"
29 #include "media/base/yuv_scale.h"
30 #include "media/player/wtl_renderer.h"
31
32 #include "media/player/movie.h"
33
34 #ifdef TESTING
35 // Fetch current time as milliseconds.
36 // Return as double for high duration and precision.
37 static inline double GetTime() {
38 LARGE_INTEGER perf_time, perf_hz;
39 QueryPerformanceFrequency(&perf_hz); // May change with speed step.
40 QueryPerformanceCounter(&perf_time);
41 return perf_time.QuadPart * 1000.0 / perf_hz.QuadPart; // Convert to ms.
42 }
43 #endif
44
45 extern bool g_enableswscaler;
46 extern bool g_enabledraw;
47 extern bool g_enabledump_yuv_file;
48 extern int g_view_size;
49
50 class WtlVideoWindow : public CScrollWindowImpl<WtlVideoWindow> {
51 public:
52 DECLARE_WND_CLASS_EX(NULL, 0, -1)
53
54 BEGIN_MSG_MAP(WtlVideoWindow)
55 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
56 CHAIN_MSG_MAP(CScrollWindowImpl<WtlVideoWindow>);
57 END_MSG_MAP()
58
59 WtlVideoWindow() {
60 size_.cx = 0;
61 size_.cy = 0;
62 renderer_ = new WtlVideoRenderer(this);
63 last_frame_ = NULL;
64 }
65
66 BOOL PreTranslateMessage(MSG* /*msg*/) {
67 return FALSE;
68 }
69
70 void AllocateVideoBitmap(CDCHandle dc) {
71 // See note on SetSize for why we check size_.cy.
72 if (bmp_.IsNull() && size_.cy > 0) {
73 BITMAPINFO bmi;
74 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
75 bmi.bmiHeader.biWidth = size_.cx;
76 bmi.bmiHeader.biHeight = size_.cy;
77 bmi.bmiHeader.biPlanes = 1;
78 bmi.bmiHeader.biBitCount = 32;
79 bmi.bmiHeader.biCompression = BI_RGB;
80 bmi.bmiHeader.biSizeImage = 0;
81 bmi.bmiHeader.biXPelsPerMeter = 100;
82 bmi.bmiHeader.biYPelsPerMeter = 100;
83 bmi.bmiHeader.biClrUsed = 0;
84 bmi.bmiHeader.biClrImportant = 0;
85 void* pBits;
86 bmp_.CreateDIBSection(dc, &bmi, DIB_RGB_COLORS, &pBits, NULL, 0);
87 SetScrollOffset(0, 0, FALSE);
88 SetScrollSize(size_);
89 }
90 }
91
92 // Called on the video renderer's thread.
93 // Note that AllocateVideoBitmap examines the size_.cy value to determine
94 // if a bitmap should be allocated, so we set it last to avoid a race
95 // condition.
96 void SetSize(int cx, int cy) {
97 size_.cx = cx;
98 size_.cy = cy;
99 }
100
101 void Reset() {
102 if (!bmp_.IsNull()) {
103 bmp_.DeleteObject();
104 }
105 size_.cx = 0;
106 size_.cy = 0;
107 // TODO(frank): get rid of renderer at reset too.
108 }
109
110 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/,
111 BOOL& /*bHandled*/) {
112 CDCHandle dc = reinterpret_cast<HDC>(wParam);
113 AllocateVideoBitmap(dc);
114 RECT rect;
115 GetClientRect(&rect);
116 int x = 0;
117 int y = 0;
118 if (!bmp_.IsNull()) {
119 x = size_.cx + 1;
120 y = size_.cy + 1;
121 }
122 if (rect.right > m_sizeAll.cx) {
123 RECT rectRight = rect;
124 rectRight.left = x;
125 rectRight.bottom = y;
126 dc.FillRect(&rectRight, COLOR_WINDOW);
127 }
128 if (rect.bottom > m_sizeAll.cy) {
129 RECT rectBottom = rect;
130 rectBottom.top = y;
131 dc.FillRect(&rectBottom, COLOR_WINDOW);
132 }
133 if (!bmp_.IsNull()) {
134 dc.MoveTo(size_.cx, 0);
135 dc.LineTo(size_.cx, size_.cy);
136 dc.LineTo(0, size_.cy);
137 }
138 return 0;
139 }
140
141 // Convert the video frame to RGB and Blit.
142 void ConvertFrame(media::VideoFrame * video_frame) {
143 media::VideoSurface frame_in;
144 bool lock_result = video_frame->Lock(&frame_in);
145 DCHECK(lock_result);
146 BITMAP bm;
147 bmp_.GetBitmap(&bm);
148 int dibwidth = bm.bmWidth;
149 int dibheight = bm.bmHeight;
150
151 uint8 *movie_dib_bits = reinterpret_cast<uint8 *>(bm.bmBits) +
152 bm.bmWidthBytes * (bm.bmHeight - 1);
153 int dibrowbytes = -bm.bmWidthBytes;
154 int clipped_width = frame_in.width;
155 if (dibwidth < clipped_width) {
156 clipped_width = dibwidth;
157 }
158 int clipped_height = frame_in.height;
159 if (dibheight < clipped_height) {
160 clipped_height = dibheight;
161 }
162
163 int scaled_width = clipped_width;
164 int scaled_height = clipped_height;
165 switch (g_view_size) {
166 case 0:
167 scaled_width = clipped_width / 2;
168 scaled_height = clipped_height / 2;
169 break;
170
171 case 1:
172 default: // Assume 1:1 for stray view sizes
173 scaled_width = clipped_width;
174 scaled_height = clipped_height;
175 break;
176
177 case 2:
178 scaled_width = clipped_width;
179 scaled_height = clipped_height;
180 clipped_width = scaled_width / 2;
181 clipped_height = scaled_height / 2;
182 break;
183 }
184
185 // Append each frame to end of file.
186 if (g_enabledump_yuv_file) {
187 DumpYUV(frame_in);
188 }
189
190 #ifdef TESTING
191 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
192 double yuvtimestart = GetTime(); // Start timer.
193 #endif
194
195 if (g_enabledraw) {
196 if (g_enableswscaler) {
197 uint8* data_out[3];
198 int stride_out[3];
199 data_out[0] = movie_dib_bits;
200 data_out[1] = NULL;
201 data_out[2] = NULL;
202 stride_out[0] = dibrowbytes;
203 stride_out[1] = 0;
204 stride_out[2] = 0;
205
206 /*
207 if (!sws_context_) {
208 DCHECK(frame_in.format == VideoSurface::YV12);
209 int outtype = bm.bmBitsPixel == 32 ? PIX_FMT_RGB32 : PIX_FMT_RGB24;
210 sws_context_ = sws_getContext(frame_in.width, frame_in.height,
211 PIX_FMT_YUV420P, width_, height_,
212 outtype, SWS_FAST_BILINEAR,
213 NULL, NULL, NULL);
214 DCHECK(sws_context_);
215 }
216
217 sws_scale(sws_context_, frame_in.data, frame_in.strides, 0,
218 height_, data_out, stride_out);
219 */
220 } else {
221 DCHECK(bm.bmBitsPixel == 32);
222 DrawYUV(frame_in,
223 movie_dib_bits,
224 dibrowbytes,
225 clipped_width,
226 clipped_height,
227 scaled_width,
228 scaled_height);
229 }
230 }
231 #ifdef TESTING
232 double yuvtimeend = GetTime(); // Start timer.
233 SSetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
234 static int yuvtimecount = 0;
235 static double yuvtimesum = 0;
236 yuvtimesum += yuvtimeend - yuvtimestart;
237 ++yuvtimecount;
238
239 char outputbuf[512];
240 snprintf(outputbuf, sizeof(outputbuf), "yuv %.2fms avg %.2fms\n",
241 yuvtimeend - yuvtimestart, yuvtimesum / yuvtimecount);
242 OutputDebugStringA(outputbuf);
243 #endif
244 }
245
246 void DoPaint(CDCHandle dc) {
247 AllocateVideoBitmap(dc);
248 if (!bmp_.IsNull()) {
249 scoped_refptr<media::VideoFrame> frame;
250 renderer_->GetCurrentFrame(&frame);
251 if (frame.get()) {
252 base::TimeDelta frame_timestamp = frame->GetTimestamp();
253 if (frame != last_frame_ || frame_timestamp != last_timestamp_) {
254 last_frame_ = frame;
255 last_timestamp_ = frame_timestamp;
256 ConvertFrame(frame);
257 }
258 frame = NULL;
259 }
260
261 #ifdef TESTING
262 double paint_time_start = GetTime();
263 static double paint_time_previous = 0;
264 if (!paint_time_previous)
265 paint_time_previous = paint_time_start;
266 #endif
267 CDC dcMem;
268 dcMem.CreateCompatibleDC(dc);
269 HBITMAP hBmpOld = dcMem.SelectBitmap(bmp_);
270 dc.BitBlt(0, 0, size_.cx, size_.cy, dcMem, 0, 0, SRCCOPY);
271 dcMem.SelectBitmap(hBmpOld);
272 #ifdef TESTING
273 double paint_time_end = GetTime();
274 static int paint_count = 0;
275 static double paint_time_sum = 0;
276 paint_time_sum += paint_time_end-paint_time_start;
277 ++paint_count;
278 char outputbuf[512];
279 snprintf(outputbuf, sizeof(outputbuf),
280 "paint time %5.2fms blit %5.2fms avg %5.2fms\n",
281 paint_time_start-paint_time_previous,
282 paint_time_end-paint_time_start,
283 paint_time_sum/paint_count);
284 OutputDebugStringA(outputbuf);
285
286 paint_time_previous = paint_time_start;
287 #endif
288 }
289 } // End of DoPaint function.
290
291 CBitmap bmp_; // Used by mainfrm.h.
292 SIZE size_; // Used by WtlVideoWindow.
293 scoped_refptr<WtlVideoRenderer> renderer_; // Used by WtlVideoWindow.
294
295 private:
296
297 // Draw a frame of YUV to an RGB buffer with scaling.
298 // Handles different YUV formats.
299 void DrawYUV(const media::VideoSurface &frame_in,
300 uint8 *movie_dib_bits,
301 int dibrowbytes,
302 int clipped_width,
303 int clipped_height,
304 int scaled_width,
305 int scaled_height) {
306 // Normal size
307 if (g_view_size == 1) {
308 if (frame_in.format == media::VideoSurface::YV16) {
309 // Temporary cast, til we use uint8 for VideoFrame.
310 media::ConvertYV16ToRGB32((const uint8*)frame_in.data[0],
311 (const uint8*)frame_in.data[1],
312 (const uint8*)frame_in.data[2],
313 movie_dib_bits,
314 clipped_width, clipped_height,
315 frame_in.strides[0],
316 frame_in.strides[1],
317 dibrowbytes);
318 } else {
319 // Temporary cast, til we use uint8 for VideoFrame.
320 media::ConvertYV12ToRGB32((const uint8*)frame_in.data[0],
321 (const uint8*)frame_in.data[1],
322 (const uint8*)frame_in.data[2],
323 movie_dib_bits,
324 clipped_width, clipped_height,
325 frame_in.strides[0],
326 frame_in.strides[1],
327 dibrowbytes);
328 }
329 } else {
330 if (frame_in.format == media::VideoSurface::YV16) {
331 // Temporary cast, til we use uint8 for VideoFrame.
332 media::ScaleYV16ToRGB32((const uint8*)frame_in.data[0],
333 (const uint8*)frame_in.data[1],
334 (const uint8*)frame_in.data[2],
335 movie_dib_bits,
336 clipped_width, clipped_height,
337 scaled_width, scaled_height,
338 frame_in.strides[0],
339 frame_in.strides[1],
340 dibrowbytes);
341 } else {
342 // Temporary cast, til we use uint8 for VideoFrame.
343 media::ScaleYV12ToRGB32((const uint8*)frame_in.data[0],
344 (const uint8*)frame_in.data[1],
345 (const uint8*)frame_in.data[2],
346 movie_dib_bits,
347 clipped_width, clipped_height,
348 scaled_width, scaled_height,
349 frame_in.strides[0],
350 frame_in.strides[1],
351 dibrowbytes);
352 }
353 }
354 }
355
356 // Diagnostic function to write out YUV in format compatible with PYUV tool.
357 void DumpYUV(const media::VideoSurface &frame_in) {
358 FILE * file_yuv = fopen("raw.yuv", "ab+"); // Open for append binary.
359 if (file_yuv != NULL) {
360 fseek(file_yuv, 0, SEEK_END);
361 const size_t frame_size = frame_in.width * frame_in.height;
362 for (size_t y = 0; y < frame_in.height; ++y)
363 fwrite(frame_in.data[0]+frame_in.strides[0]*y,
364 frame_in.width, sizeof(uint8), file_yuv);
365 for (size_t y = 0; y < frame_in.height/2; ++y)
366 fwrite(frame_in.data[1]+frame_in.strides[1]*y,
367 frame_in.width/2, sizeof(uint8), file_yuv);
368 for (size_t y = 0; y < frame_in.height/2; ++y)
369 fwrite(frame_in.data[2]+frame_in.strides[2]*y,
370 frame_in.width/2, sizeof(uint8), file_yuv);
371 fclose(file_yuv);
372
373 #if TESTING
374 static int frame_dump_count = 0;
375 char outputbuf[512];
376 snprintf(outputbuf, sizeof(outputbuf), "yuvdump %4d %dx%d stride %d\n",
377 frame_dump_count, frame_in.width, frame_in.height,
378 frame_in.strides[0]);
379 OutputDebugStringA(outputbuf);
380 ++frame_dump_count;
381 #endif
382 }
383 }
384
385 media::VideoFrame* last_frame_;
386 base::TimeDelta last_timestamp_;
387
388 DISALLOW_COPY_AND_ASSIGN(WtlVideoWindow);
389 };
390
391 #endif // MEDIA_PLAYER_VIEW_H_
392
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698