OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/webmediaplayer_ms_compositor.h" | 5 #include "content/renderer/media/webmediaplayer_ms_compositor.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/hash.h" | 11 #include "base/hash.h" |
12 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
13 #include "base/values.h" | 13 #include "base/values.h" |
14 #include "content/common/gpu/client/context_provider_command_buffer.h" | 14 #include "content/common/gpu/client/context_provider_command_buffer.h" |
15 #include "content/renderer/media/webmediaplayer_ms.h" | 15 #include "content/renderer/media/webmediaplayer_ms.h" |
16 #include "content/renderer/render_thread_impl.h" | 16 #include "content/renderer/render_thread_impl.h" |
17 #include "media/base/media_switches.h" | 17 #include "media/base/media_switches.h" |
18 #include "media/base/video_frame.h" | 18 #include "media/base/video_frame.h" |
19 #include "media/base/video_util.h" | 19 #include "media/base/video_util.h" |
20 #include "media/filters/video_renderer_algorithm.h" | 20 #include "media/filters/video_renderer_algorithm.h" |
21 #include "media/renderers/skcanvas_video_renderer.h" | 21 #include "media/renderers/skcanvas_video_renderer.h" |
22 #include "skia/ext/platform_canvas.h" | 22 #include "skia/ext/platform_canvas.h" |
23 #include "third_party/WebKit/public/platform/WebMediaStream.h" | 23 #include "third_party/WebKit/public/platform/WebMediaStream.h" |
24 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" | 24 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" |
25 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" | 25 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" |
26 #include "third_party/libyuv/include/libyuv/convert.h" | 26 #include "third_party/libyuv/include/libyuv/convert.h" |
27 #include "third_party/libyuv/include/libyuv/planar_functions.h" | 27 #include "third_party/libyuv/include/libyuv/planar_functions.h" |
28 #include "third_party/libyuv/include/libyuv/video_common.h" | 28 #include "third_party/libyuv/include/libyuv/video_common.h" |
29 #include "third_party/skia/include/core/SkSurface.h" | |
29 | 30 |
30 namespace content { | 31 namespace content { |
31 | 32 |
32 namespace { | 33 namespace { |
33 | 34 |
34 // This function copies |frame| to a new I420 or YV12A media::VideoFrame. | 35 // This function copies |frame| to a new I420 or YV12A media::VideoFrame. |
35 scoped_refptr<media::VideoFrame> CopyFrame( | 36 scoped_refptr<media::VideoFrame> CopyFrame( |
36 const scoped_refptr<media::VideoFrame>& frame, | 37 const scoped_refptr<media::VideoFrame>& frame, |
37 media::SkCanvasVideoRenderer* video_renderer) { | 38 media::SkCanvasVideoRenderer* video_renderer) { |
38 scoped_refptr<media::VideoFrame> new_frame; | 39 scoped_refptr<media::VideoFrame> new_frame; |
39 if (frame->HasTextures()) { | 40 if (frame->HasTextures()) { |
40 DCHECK(frame->format() == media::PIXEL_FORMAT_ARGB || | 41 DCHECK(frame->format() == media::PIXEL_FORMAT_ARGB || |
41 frame->format() == media::PIXEL_FORMAT_XRGB || | 42 frame->format() == media::PIXEL_FORMAT_XRGB || |
42 frame->format() == media::PIXEL_FORMAT_I420 || | 43 frame->format() == media::PIXEL_FORMAT_I420 || |
43 frame->format() == media::PIXEL_FORMAT_UYVY || | 44 frame->format() == media::PIXEL_FORMAT_UYVY || |
44 frame->format() == media::PIXEL_FORMAT_NV12); | 45 frame->format() == media::PIXEL_FORMAT_NV12); |
45 new_frame = media::VideoFrame::CreateFrame( | 46 new_frame = media::VideoFrame::CreateFrame( |
46 media::PIXEL_FORMAT_I420, frame->coded_size(), frame->visible_rect(), | 47 media::PIXEL_FORMAT_I420, frame->coded_size(), frame->visible_rect(), |
47 frame->natural_size(), frame->timestamp()); | 48 frame->natural_size(), frame->timestamp()); |
48 SkBitmap bitmap; | |
49 bitmap.allocN32Pixels(frame->visible_rect().width(), | |
50 frame->visible_rect().height()); | |
51 SkCanvas canvas(bitmap); | |
52 | 49 |
53 auto* provider = | 50 // TODO(mcasas): Reuse |surface| (as long as frame->visible_rect() doesn't |
Daniele Castagna
2016/07/18 16:51:23
Why? Is it expensive to create one?
mcasas
2016/07/18 17:40:42
It boils down to creating a Raster N32 memory, whi
emircan
2016/07/18 18:24:25
Since the use-case here is for pausing media strea
mcasas
2016/07/18 18:33:14
Oh gotcha, removing the TODO then.
| |
51 // change) by moving it and CopyFrame() to WebMediaPlayerMSCompositor. | |
52 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul( | |
53 frame->visible_rect().width(), frame->visible_rect().height()); | |
54 | |
55 ContextProviderCommandBuffer* const provider = | |
54 RenderThreadImpl::current()->SharedMainThreadContextProvider().get(); | 56 RenderThreadImpl::current()->SharedMainThreadContextProvider().get(); |
55 if (provider) { | 57 if (surface && provider) { |
Daniele Castagna
2016/07/18 16:51:23
It seems like surface can be null only if we can't
mcasas
2016/07/18 17:40:43
It could also be null due to incorrect width/heigh
| |
56 const media::Context3D context_3d = | 58 DCHECK(provider->ContextGL()); |
57 media::Context3D(provider->ContextGL(), provider->GrContext()); | 59 video_renderer->Copy( |
58 DCHECK(context_3d.gl); | 60 frame.get(), surface->getCanvas(), |
59 video_renderer->Copy(frame.get(), &canvas, context_3d); | 61 media::Context3D(provider->ContextGL(), provider->GrContext())); |
60 } else { | 62 } else { |
61 // GPU Process crashed. | 63 // Return a black frame (yuv = {0, 0x80, 0x80}). |
62 bitmap.eraseColor(SK_ColorTRANSPARENT); | 64 return media::VideoFrame::CreateColorFrame( |
65 frame->visible_rect().size(), 0u, 0x80, 0x80, frame->timestamp()); | |
63 } | 66 } |
64 libyuv::ARGBToI420(reinterpret_cast<uint8_t*>(bitmap.getPixels()), | 67 |
65 bitmap.rowBytes(), | 68 SkPixmap pixmap; |
66 new_frame->visible_data(media::VideoFrame::kYPlane), | 69 const bool result = surface->getCanvas()->peekPixels(&pixmap); |
67 new_frame->stride(media::VideoFrame::kYPlane), | 70 DCHECK(result) << "Error trying to access SkSurface's pixels"; |
68 new_frame->visible_data(media::VideoFrame::kUPlane), | 71 |
69 new_frame->stride(media::VideoFrame::kUPlane), | 72 const uint32 source_pixel_format = |
70 new_frame->visible_data(media::VideoFrame::kVPlane), | 73 (kN32_SkColorType == kRGBA_8888_SkColorType) ? libyuv::FOURCC_ABGR |
71 new_frame->stride(media::VideoFrame::kVPlane), | 74 : libyuv::FOURCC_ARGB; |
72 bitmap.width(), bitmap.height()); | 75 libyuv::ConvertToI420( |
76 static_cast<uint8*>(pixmap.writable_addr(0, 0)), | |
Daniele Castagna
2016/07/18 16:51:23
nit: can you use addr instead of writable_addr?
mcasas
2016/07/18 17:40:43
Good catch, done
| |
77 pixmap.getSize64(), | |
Daniele Castagna
2016/07/18 16:51:23
nit: getSafeSize64 seems to be <= than size64, sho
mcasas
2016/07/18 17:40:43
Done.
| |
78 new_frame->data(media::VideoFrame::kYPlane), | |
emircan
2016/07/18 18:24:25
Consider the case for coded_size() is different th
mcasas
2016/07/18 18:33:14
Done.
| |
79 new_frame->stride(media::VideoFrame::kYPlane), | |
80 new_frame->data(media::VideoFrame::kUPlane), | |
81 new_frame->stride(media::VideoFrame::kUPlane), | |
82 new_frame->data(media::VideoFrame::kVPlane), | |
83 new_frame->stride(media::VideoFrame::kVPlane), 0 /* crop_x */, | |
84 0 /* crop_y */, pixmap.width(), pixmap.height(), | |
85 new_frame->coded_size().width(), new_frame->coded_size().height(), | |
86 libyuv::kRotate0, source_pixel_format); | |
73 } else { | 87 } else { |
74 DCHECK(frame->IsMappable()); | 88 DCHECK(frame->IsMappable()); |
75 DCHECK(frame->format() == media::PIXEL_FORMAT_YV12 || | 89 DCHECK(frame->format() == media::PIXEL_FORMAT_YV12 || |
76 frame->format() == media::PIXEL_FORMAT_YV12A || | 90 frame->format() == media::PIXEL_FORMAT_YV12A || |
77 frame->format() == media::PIXEL_FORMAT_I420); | 91 frame->format() == media::PIXEL_FORMAT_I420); |
78 const gfx::Size& coded_size = frame->coded_size(); | 92 const gfx::Size& coded_size = frame->coded_size(); |
79 new_frame = media::VideoFrame::CreateFrame( | 93 new_frame = media::VideoFrame::CreateFrame( |
80 media::IsOpaque(frame->format()) ? media::PIXEL_FORMAT_I420 | 94 media::IsOpaque(frame->format()) ? media::PIXEL_FORMAT_I420 |
81 : media::PIXEL_FORMAT_YV12A, | 95 : media::PIXEL_FORMAT_YV12A, |
82 coded_size, frame->visible_rect(), frame->natural_size(), | 96 coded_size, frame->visible_rect(), frame->natural_size(), |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
427 } | 441 } |
428 | 442 |
429 if (!rendering_frame_buffer_) { | 443 if (!rendering_frame_buffer_) { |
430 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( | 444 rendering_frame_buffer_.reset(new media::VideoRendererAlgorithm( |
431 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, | 445 base::Bind(&WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks, |
432 base::Unretained(this)))); | 446 base::Unretained(this)))); |
433 } | 447 } |
434 } | 448 } |
435 | 449 |
436 } // namespace content | 450 } // namespace content |
OLD | NEW |