OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this | 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 | 2 // source code is governed by a BSD-style license that can be found in the |
3 // LICENSE file. | 3 // LICENSE file. |
4 | 4 |
5 // View.h : Paints the current movie frame (with scaling) to the display. | 5 // View.h : Paints the current movie frame (with scaling) to the display. |
6 // TODO(fbarchard): Consider rewriting as view.cc and view.h | 6 // TODO(fbarchard): Consider rewriting as view.cc and view.h |
7 | 7 |
8 #ifndef MEDIA_PLAYER_VIEW_H_ | 8 #ifndef MEDIA_PLAYER_VIEW_H_ |
9 #define MEDIA_PLAYER_VIEW_H_ | 9 #define MEDIA_PLAYER_VIEW_H_ |
10 | 10 |
11 // Enable timing code by turning on TESTING macro. | 11 // Enable timing code by turning on TESTING macro. |
12 // #define TESTING 1 | 12 // #define TESTING 1 |
13 | 13 |
14 #ifdef TESTING | 14 #ifdef TESTING |
15 #define _CRT_SECURE_NO_WARNINGS | 15 #define _CRT_SECURE_NO_WARNINGS |
16 #include <windows.h> | 16 #include <windows.h> |
17 #include <stdio.h> | 17 #include <stdio.h> |
18 #include <process.h> | 18 #include <process.h> |
19 #include <string.h> | 19 #include <string.h> |
20 #endif | 20 #endif |
21 | 21 |
| 22 // Enable swscaler. |
| 23 // TODO(fbarchard): Include header and change bilinear to point sampling. |
| 24 // #define TEST_SWSCALER 1 |
| 25 |
22 #include <atlscrl.h> | 26 #include <atlscrl.h> |
23 | 27 |
24 #include "base/basictypes.h" | 28 #include "base/basictypes.h" |
25 #include "media/base/buffers.h" | 29 #include "media/base/buffers.h" |
26 #include "media/base/factory.h" | 30 #include "media/base/factory.h" |
27 #include "media/base/filters.h" | 31 #include "media/base/filters.h" |
28 #include "media/base/yuv_convert.h" | 32 #include "media/base/yuv_convert.h" |
29 #include "media/base/yuv_scale.h" | |
30 #include "media/player/movie.h" | 33 #include "media/player/movie.h" |
31 #include "media/player/wtl_renderer.h" | 34 #include "media/player/wtl_renderer.h" |
32 | 35 |
33 #ifdef TESTING | 36 #ifdef TESTING |
34 // Fetch current time as milliseconds. | 37 // Fetch current time as milliseconds. |
35 // Return as double for high duration and precision. | 38 // Return as double for high duration and precision. |
36 static inline double GetTime() { | 39 static inline double GetTime() { |
37 LARGE_INTEGER perf_time, perf_hz; | 40 LARGE_INTEGER perf_time, perf_hz; |
38 QueryPerformanceFrequency(&perf_hz); // May change with speed step. | 41 QueryPerformanceFrequency(&perf_hz); // May change with speed step. |
39 QueryPerformanceCounter(&perf_time); | 42 QueryPerformanceCounter(&perf_time); |
40 return perf_time.QuadPart * 1000.0 / perf_hz.QuadPart; // Convert to ms. | 43 return perf_time.QuadPart * 1000.0 / perf_hz.QuadPart; // Convert to ms. |
41 } | 44 } |
42 #endif | 45 #endif |
43 | 46 |
44 class WtlVideoWindow : public CScrollWindowImpl<WtlVideoWindow> { | 47 class WtlVideoWindow : public CScrollWindowImpl<WtlVideoWindow> { |
45 public: | 48 public: |
46 DECLARE_WND_CLASS_EX(NULL, 0, -1) | 49 DECLARE_WND_CLASS_EX(NULL, 0, -1) |
47 | 50 |
48 BEGIN_MSG_MAP(WtlVideoWindow) | 51 BEGIN_MSG_MAP(WtlVideoWindow) |
49 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) | 52 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) |
50 CHAIN_MSG_MAP(CScrollWindowImpl<WtlVideoWindow>); | 53 CHAIN_MSG_MAP(CScrollWindowImpl<WtlVideoWindow>); |
51 END_MSG_MAP() | 54 END_MSG_MAP() |
52 | 55 |
53 WtlVideoWindow() { | 56 WtlVideoWindow() { |
54 size_.cx = 0; | 57 size_.cx = 0; |
55 size_.cy = 0; | 58 size_.cy = 0; |
56 view_size_ = 1; | 59 view_size_ = 2; // Normal size. |
57 view_rotate_ = media::ROTATE_0; | 60 view_rotate_ = media::ROTATE_0; |
58 renderer_ = new WtlVideoRenderer(this); | 61 renderer_ = new WtlVideoRenderer(this); |
59 last_frame_ = NULL; | 62 last_frame_ = NULL; |
60 hbmp_ = NULL; | 63 hbmp_ = NULL; |
61 } | 64 } |
62 | 65 |
63 BOOL PreTranslateMessage(MSG* /*msg*/) { | 66 BOOL PreTranslateMessage(MSG* /*msg*/) { |
64 return FALSE; | 67 return FALSE; |
65 } | 68 } |
66 | 69 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 } | 157 } |
155 int clipped_height = frame_in.height; | 158 int clipped_height = frame_in.height; |
156 if (dibheight < clipped_height) { | 159 if (dibheight < clipped_height) { |
157 clipped_height = dibheight; | 160 clipped_height = dibheight; |
158 } | 161 } |
159 | 162 |
160 int scaled_width = clipped_width; | 163 int scaled_width = clipped_width; |
161 int scaled_height = clipped_height; | 164 int scaled_height = clipped_height; |
162 switch (view_size_) { | 165 switch (view_size_) { |
163 case 0: | 166 case 0: |
| 167 scaled_width = clipped_width / 4; |
| 168 scaled_height = clipped_height / 4; |
| 169 break; |
| 170 |
| 171 case 1: |
164 scaled_width = clipped_width / 2; | 172 scaled_width = clipped_width / 2; |
165 scaled_height = clipped_height / 2; | 173 scaled_height = clipped_height / 2; |
166 break; | 174 break; |
167 | 175 |
168 case 1: | 176 case 2: |
169 default: // Assume 1:1 for stray view sizes | 177 default: // Assume 1:1 for stray view sizes. |
170 scaled_width = clipped_width; | 178 scaled_width = clipped_width; |
171 scaled_height = clipped_height; | 179 scaled_height = clipped_height; |
172 break; | 180 break; |
173 | 181 |
174 case 2: | 182 case 3: // Double. |
175 scaled_width = clipped_width; | 183 scaled_width = clipped_width; |
176 scaled_height = clipped_height; | 184 scaled_height = clipped_height; |
177 clipped_width = scaled_width / 2; | 185 clipped_width = scaled_width / 2; |
178 clipped_height = scaled_height / 2; | 186 clipped_height = scaled_height / 2; |
179 break; | 187 break; |
| 188 |
| 189 case 4: // Triple. |
| 190 scaled_width = clipped_width; |
| 191 scaled_height = clipped_height; |
| 192 clipped_width = scaled_width / 3; |
| 193 clipped_height = scaled_height / 3; |
| 194 break; |
| 195 |
| 196 case 5: // Quadruple. |
| 197 scaled_width = clipped_width; |
| 198 scaled_height = clipped_height; |
| 199 clipped_width = scaled_width / 4; |
| 200 clipped_height = scaled_height / 4; |
| 201 break; |
180 } | 202 } |
181 | 203 |
182 // Append each frame to end of file. | 204 // Append each frame to end of file. |
183 bool enable_dump_yuv_file = media::Movie::get()->GetDumpYuvFileEnable(); | 205 bool enable_dump_yuv_file = media::Movie::get()->GetDumpYuvFileEnable(); |
184 if (enable_dump_yuv_file) { | 206 if (enable_dump_yuv_file) { |
185 DumpYUV(frame_in); | 207 DumpYUV(frame_in); |
186 } | 208 } |
187 | 209 |
188 #ifdef TESTING | 210 #ifdef TESTING |
189 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); | 211 double yuv_time_start = GetTime(); // Start timer. |
190 double yuvtimestart = GetTime(); // Start timer. | |
191 #endif | 212 #endif |
192 | 213 |
193 bool enable_draw = media::Movie::get()->GetDrawEnable(); | 214 bool enable_draw = media::Movie::get()->GetDrawEnable(); |
194 if (enable_draw) { | 215 if (enable_draw) { |
| 216 #ifdef TEST_SWSCALER |
195 bool enable_swscaler = media::Movie::get()->GetSwscalerEnable(); | 217 bool enable_swscaler = media::Movie::get()->GetSwscalerEnable(); |
196 if (enable_swscaler) { | 218 if (enable_swscaler) { |
197 uint8* data_out[3]; | 219 uint8* data_out[3]; |
198 int stride_out[3]; | 220 int stride_out[3]; |
199 data_out[0] = movie_dib_bits; | 221 data_out[0] = movie_dib_bits; |
200 data_out[1] = NULL; | 222 data_out[1] = NULL; |
201 data_out[2] = NULL; | 223 data_out[2] = NULL; |
202 stride_out[0] = dibrowbytes; | 224 stride_out[0] = dibrowbytes; |
203 stride_out[1] = 0; | 225 stride_out[1] = 0; |
204 stride_out[2] = 0; | 226 stride_out[2] = 0; |
205 | 227 |
206 /* | |
207 if (!sws_context_) { | 228 if (!sws_context_) { |
208 DCHECK(frame_in.format == VideoSurface::YV12); | 229 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, | 230 sws_context_ = sws_getContext(frame_in.width, frame_in.height, |
211 PIX_FMT_YUV420P, width_, height_, | 231 PIX_FMT_YUV420P, width_, height_, |
212 outtype, SWS_FAST_BILINEAR, | 232 PIX_FMT_RGB32, SWS_FAST_BILINEAR, |
213 NULL, NULL, NULL); | 233 NULL, NULL, NULL); |
214 DCHECK(sws_context_); | 234 DCHECK(sws_context_); |
215 } | 235 } |
216 | 236 |
217 sws_scale(sws_context_, frame_in.data, frame_in.strides, 0, | 237 sws_scale(sws_context_, frame_in.data, frame_in.strides, 0, |
218 height_, data_out, stride_out); | 238 height_, data_out, stride_out); |
219 */ | |
220 } else { | 239 } else { |
| 240 #endif |
221 DCHECK(bm.bmBitsPixel == 32); | 241 DCHECK(bm.bmBitsPixel == 32); |
222 DrawYUV(frame_in, | 242 DrawYUV(frame_in, |
223 movie_dib_bits, | 243 movie_dib_bits, |
224 dibrowbytes, | 244 dibrowbytes, |
225 clipped_width, | 245 clipped_width, |
226 clipped_height, | 246 clipped_height, |
227 scaled_width, | 247 scaled_width, |
228 scaled_height); | 248 scaled_height); |
| 249 #ifdef TEST_SWSCALER |
229 } | 250 } |
| 251 #endif |
230 } | 252 } |
231 #ifdef TESTING | 253 #ifdef TESTING |
232 double yuvtimeend = GetTime(); // Start timer. | 254 double yuv_time_end = GetTime(); |
233 SSetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); | 255 static int yuv_time_count = 0; |
234 static int yuvtimecount = 0; | 256 static double yuv_time_sum = 0.; |
235 static double yuvtimesum = 0; | 257 if (!yuv_time_count) |
236 yuvtimesum += yuvtimeend - yuvtimestart; | 258 yuv_time_sum = 0.; |
237 ++yuvtimecount; | 259 yuv_time_sum += (yuv_time_end - yuv_time_start); |
| 260 ++yuv_time_count; |
238 | 261 |
239 char outputbuf[512]; | 262 char outputbuf[512]; |
240 snprintf(outputbuf, sizeof(outputbuf), "yuv %.2fms avg %.2fms\n", | 263 _snprintf_s(outputbuf, sizeof(outputbuf), "test %f", yuv_time_end); |
241 yuvtimeend - yuvtimestart, yuvtimesum / yuvtimecount); | 264 _snprintf_s(outputbuf, sizeof(outputbuf), |
| 265 "yuv %5.2f ms avg %5.2f ms\n", |
| 266 yuv_time_end - yuv_time_start, |
| 267 yuv_time_sum / yuv_time_count); |
242 OutputDebugStringA(outputbuf); | 268 OutputDebugStringA(outputbuf); |
243 #endif | 269 #endif |
244 } | 270 } |
245 | 271 |
246 void DoPaint(CDCHandle dc) { | 272 void DoPaint(CDCHandle dc) { |
247 AllocateVideoBitmap(dc); | 273 AllocateVideoBitmap(dc); |
248 if (!bmp_.IsNull()) { | 274 if (!bmp_.IsNull()) { |
249 scoped_refptr<media::VideoFrame> frame; | 275 scoped_refptr<media::VideoFrame> frame; |
250 renderer_->GetCurrentFrame(&frame); | 276 renderer_->GetCurrentFrame(&frame); |
251 if (frame.get()) { | 277 if (frame.get()) { |
(...skipping 14 matching lines...) Expand all Loading... |
266 #endif | 292 #endif |
267 CDC dcMem; | 293 CDC dcMem; |
268 dcMem.CreateCompatibleDC(dc); | 294 dcMem.CreateCompatibleDC(dc); |
269 HBITMAP hBmpOld = hbmp_ ? hbmp_: dcMem.SelectBitmap(bmp_); | 295 HBITMAP hBmpOld = hbmp_ ? hbmp_: dcMem.SelectBitmap(bmp_); |
270 dc.BitBlt(0, 0, size_.cx, size_.cy, dcMem, 0, 0, SRCCOPY); | 296 dc.BitBlt(0, 0, size_.cx, size_.cy, dcMem, 0, 0, SRCCOPY); |
271 dcMem.SelectBitmap(hBmpOld); | 297 dcMem.SelectBitmap(hBmpOld); |
272 #ifdef TESTING | 298 #ifdef TESTING |
273 double paint_time_end = GetTime(); | 299 double paint_time_end = GetTime(); |
274 static int paint_count = 0; | 300 static int paint_count = 0; |
275 static double paint_time_sum = 0; | 301 static double paint_time_sum = 0; |
276 paint_time_sum += paint_time_end-paint_time_start; | 302 paint_time_sum += paint_time_end - paint_time_start; |
277 ++paint_count; | 303 ++paint_count; |
278 char outputbuf[512]; | 304 char outputbuf[512]; |
279 snprintf(outputbuf, sizeof(outputbuf), | 305 _snprintf_s(outputbuf, sizeof(outputbuf), |
280 "paint time %5.2fms blit %5.2fms avg %5.2fms\n", | 306 "paint time %5.2f ms blit %5.2f ms avg %5.2f ms\n", |
281 paint_time_start-paint_time_previous, | 307 paint_time_start - paint_time_previous, |
282 paint_time_end-paint_time_start, | 308 paint_time_end - paint_time_start, |
283 paint_time_sum/paint_count); | 309 paint_time_sum / paint_count); |
284 OutputDebugStringA(outputbuf); | 310 OutputDebugStringA(outputbuf); |
285 | 311 |
286 paint_time_previous = paint_time_start; | 312 paint_time_previous = paint_time_start; |
287 #endif | 313 #endif |
288 } | 314 } |
289 } // End of DoPaint function. | 315 } // End of DoPaint function. |
290 | 316 |
291 void SetViewSize(int view_size) { | 317 void SetViewSize(int view_size) { |
292 view_size_ = view_size; | 318 view_size_ = view_size; |
293 } | 319 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 void SetBitmap(HBITMAP hbmp) { | 375 void SetBitmap(HBITMAP hbmp) { |
350 hbmp_ = hbmp; | 376 hbmp_ = hbmp; |
351 } | 377 } |
352 | 378 |
353 CBitmap bmp_; // Used by mainfrm.h. | 379 CBitmap bmp_; // Used by mainfrm.h. |
354 SIZE size_; // Used by WtlVideoWindow. | 380 SIZE size_; // Used by WtlVideoWindow. |
355 scoped_refptr<WtlVideoRenderer> renderer_; // Used by WtlVideoWindow. | 381 scoped_refptr<WtlVideoRenderer> renderer_; // Used by WtlVideoWindow. |
356 | 382 |
357 private: | 383 private: |
358 HBITMAP hbmp_; // For Images | 384 HBITMAP hbmp_; // For Images |
359 int view_size_; // View Size. 0=0.5, 1=normal, 2=2x, 3=fit, 4=full | 385 // View Size: 0=1/4, 1=0.5, 2=normal, 3=2x, 4=3x, 5=4x, 3=fit, 4=full. |
| 386 int view_size_; |
360 | 387 |
361 // View Rotate 0-5 for ID_VIEW_ROTATE0 to ID_VIEW_MIRROR_VERTICAL | 388 // View Rotate 0-5 for ID_VIEW_ROTATE0 to ID_VIEW_MIRROR_VERTICAL |
362 media::Rotate view_rotate_; | 389 media::Rotate view_rotate_; |
363 | 390 |
364 // Draw a frame of YUV to an RGB buffer with scaling. | 391 // Draw a frame of YUV to an RGB buffer with scaling. |
365 // Handles different YUV formats. | 392 // Handles different YUV formats. |
366 void DrawYUV(const media::VideoSurface &frame_in, | 393 void DrawYUV(const media::VideoSurface &frame_in, |
367 uint8 *movie_dib_bits, | 394 uint8 *movie_dib_bits, |
368 int dibrowbytes, | 395 int dibrowbytes, |
369 int clipped_width, | 396 int clipped_width, |
370 int clipped_height, | 397 int clipped_height, |
371 int scaled_width, | 398 int scaled_width, |
372 int scaled_height) { | 399 int scaled_height) { |
373 if (frame_in.format == media::VideoSurface::YV16) { | 400 media::YUVType yuv_type = (frame_in.format == media::VideoSurface::YV12) ? |
374 // Temporary cast, til we use uint8 for VideoFrame. | 401 media::YV12 : media::YV16; |
375 media::ScaleYV16ToRGB32(frame_in.data[0], | 402 |
376 frame_in.data[1], | 403 // Simple convert is not necessary for performance, but allows |
377 frame_in.data[2], | 404 // easier alternative implementations. |
378 movie_dib_bits, | 405 if ((view_rotate_ == media::ROTATE_0) && // Not scaled or rotated |
379 clipped_width, clipped_height, | 406 (view_size_ == 2)) { |
380 scaled_width, scaled_height, | 407 media::ConvertYUVToRGB32(frame_in.data[0], |
381 frame_in.strides[0], | 408 frame_in.data[1], |
382 frame_in.strides[1], | 409 frame_in.data[2], |
383 dibrowbytes, | 410 movie_dib_bits, |
384 view_rotate_); | 411 scaled_width, scaled_height, |
| 412 frame_in.strides[0], |
| 413 frame_in.strides[1], |
| 414 dibrowbytes, |
| 415 yuv_type); |
385 } else { | 416 } else { |
386 // Temporary cast, til we use uint8 for VideoFrame. | 417 media::ScaleYUVToRGB32(frame_in.data[0], |
387 media::ScaleYV12ToRGB32(frame_in.data[0], | 418 frame_in.data[1], |
388 frame_in.data[1], | 419 frame_in.data[2], |
389 frame_in.data[2], | 420 movie_dib_bits, |
390 movie_dib_bits, | 421 clipped_width, clipped_height, |
391 clipped_width, clipped_height, | 422 scaled_width, scaled_height, |
392 scaled_width, scaled_height, | 423 frame_in.strides[0], |
393 frame_in.strides[0], | 424 frame_in.strides[1], |
394 frame_in.strides[1], | 425 dibrowbytes, |
395 dibrowbytes, | 426 yuv_type, |
396 view_rotate_); | 427 view_rotate_); |
397 } | 428 } |
398 } | 429 } |
399 | 430 |
400 // Diagnostic function to write out YUV in format compatible with PYUV tool. | 431 // Diagnostic function to write out YUV in format compatible with PYUV tool. |
401 void DumpYUV(const media::VideoSurface &frame_in) { | 432 void DumpYUV(const media::VideoSurface &frame_in) { |
402 FILE * file_yuv = fopen("raw.yuv", "ab+"); // Open for append binary. | 433 FILE * file_yuv = fopen("raw.yuv", "ab+"); // Open for append binary. |
403 if (file_yuv != NULL) { | 434 if (file_yuv != NULL) { |
404 fseek(file_yuv, 0, SEEK_END); | 435 fseek(file_yuv, 0, SEEK_END); |
405 const size_t frame_size = frame_in.width * frame_in.height; | 436 const size_t frame_size = frame_in.width * frame_in.height; |
406 for (size_t y = 0; y < frame_in.height; ++y) | 437 for (size_t y = 0; y < frame_in.height; ++y) |
407 fwrite(frame_in.data[0]+frame_in.strides[0]*y, | 438 fwrite(frame_in.data[0]+frame_in.strides[0]*y, |
408 frame_in.width, sizeof(uint8), file_yuv); | 439 frame_in.width, sizeof(uint8), file_yuv); |
409 for (size_t y = 0; y < frame_in.height/2; ++y) | 440 for (size_t y = 0; y < frame_in.height/2; ++y) |
410 fwrite(frame_in.data[1]+frame_in.strides[1]*y, | 441 fwrite(frame_in.data[1]+frame_in.strides[1]*y, |
411 frame_in.width/2, sizeof(uint8), file_yuv); | 442 frame_in.width/2, sizeof(uint8), file_yuv); |
412 for (size_t y = 0; y < frame_in.height/2; ++y) | 443 for (size_t y = 0; y < frame_in.height/2; ++y) |
413 fwrite(frame_in.data[2]+frame_in.strides[2]*y, | 444 fwrite(frame_in.data[2]+frame_in.strides[2]*y, |
414 frame_in.width/2, sizeof(uint8), file_yuv); | 445 frame_in.width/2, sizeof(uint8), file_yuv); |
415 fclose(file_yuv); | 446 fclose(file_yuv); |
416 | 447 |
417 #if TESTING | 448 #if TESTING |
418 static int frame_dump_count = 0; | 449 static int frame_dump_count = 0; |
419 char outputbuf[512]; | 450 char outputbuf[512]; |
420 snprintf(outputbuf, sizeof(outputbuf), "yuvdump %4d %dx%d stride %d\n", | 451 _snprintf_s(outputbuf, sizeof(outputbuf), "yuvdump %4d %dx%d stride %d\n", |
421 frame_dump_count, frame_in.width, frame_in.height, | 452 frame_dump_count, frame_in.width, frame_in.height, |
422 frame_in.strides[0]); | 453 frame_in.strides[0]); |
423 OutputDebugStringA(outputbuf); | 454 OutputDebugStringA(outputbuf); |
424 ++frame_dump_count; | 455 ++frame_dump_count; |
425 #endif | 456 #endif |
426 } | 457 } |
427 } | 458 } |
428 | 459 |
429 media::VideoFrame* last_frame_; | 460 media::VideoFrame* last_frame_; |
430 base::TimeDelta last_timestamp_; | 461 base::TimeDelta last_timestamp_; |
431 | 462 |
432 DISALLOW_COPY_AND_ASSIGN(WtlVideoWindow); | 463 DISALLOW_COPY_AND_ASSIGN(WtlVideoWindow); |
433 }; | 464 }; |
434 | 465 |
435 #endif // MEDIA_PLAYER_VIEW_H_ | 466 #endif // MEDIA_PLAYER_VIEW_H_ |
436 | 467 |
OLD | NEW |