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

Side by Side Diff: webkit/media/crypto/ppapi/libvpx_cdm_video_decoder.cc

Issue 11316045: Add a libvpx video decoder to ClearKeyCdm and move the fake video decoder to its own class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase, fix incorrect DCHECK and fix include order. Created 8 years 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 | « webkit/media/crypto/ppapi/libvpx_cdm_video_decoder.h ('k') | webkit/media/webkit_media.gypi » ('j') | 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) 2012 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 "webkit/media/crypto/ppapi/libvpx_cdm_video_decoder.h"
6
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "media/base/buffers.h"
10 #include "media/base/limits.h"
11
12 // Include libvpx header files.
13 // VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide
14 // backwards compatibility for legacy applications using the library.
15 #define VPX_CODEC_DISABLE_COMPAT 1
16 extern "C" {
17 #include "third_party/libvpx/libvpx.h"
18 }
19
20 #include "webkit/media/crypto/ppapi/content_decryption_module.h"
21
22 // Enable USE_COPYPLANE_WITH_LIBVPX to use |CopyPlane()| instead of memcpy to
23 // copy video frame data.
24 // #define USE_COPYPLANE_WITH_LIBVPX 1
25
26 namespace webkit_media {
27
28 static const int kDecodeThreads = 1;
29
30 static void CopyPlane(const uint8_t* source,
31 int32_t source_stride,
32 int32_t target_stride,
33 int32_t rows,
34 int32_t copy_bytes_per_row,
35 uint8_t* target) {
36 DCHECK(source);
37 DCHECK(target);
38 DCHECK_LE(copy_bytes_per_row, source_stride);
39 DCHECK_LE(copy_bytes_per_row, target_stride);
40
41 for (int i = 0; i < rows; ++i) {
42 const int source_offset = i * source_stride;
43 const int target_offset = i * target_stride;
44 memcpy(target + target_offset,
45 source + source_offset,
46 copy_bytes_per_row);
47 }
48 }
49
50 LibvpxCdmVideoDecoder::LibvpxCdmVideoDecoder(cdm::Allocator* allocator)
51 : is_initialized_(false),
52 allocator_(allocator),
53 vpx_codec_(NULL),
54 vpx_image_(NULL) {
55 }
56
57 LibvpxCdmVideoDecoder::~LibvpxCdmVideoDecoder() {
58 Deinitialize();
59 }
60
61 bool LibvpxCdmVideoDecoder::Initialize(const cdm::VideoDecoderConfig& config) {
62 DVLOG(1) << "Initialize()";
63
64 if (!IsValidOutputConfig(config.format, config.coded_size)) {
65 LOG(ERROR) << "Initialize(): invalid video decoder configuration.";
66 return false;
67 }
68
69 if (is_initialized_) {
70 LOG(ERROR) << "Initialize(): Already initialized.";
71 return false;
72 }
73
74 vpx_codec_ = new vpx_codec_ctx();
75 vpx_codec_dec_cfg_t vpx_config = {0};
76 vpx_config.w = config.coded_size.width;
77 vpx_config.h = config.coded_size.height;
78 vpx_config.threads = kDecodeThreads;
79
80 vpx_codec_err_t status = vpx_codec_dec_init(vpx_codec_,
81 vpx_codec_vp8_dx(),
82 &vpx_config,
83 0);
84 if (status != VPX_CODEC_OK) {
85 LOG(ERROR) << "InitializeLibvpx(): vpx_codec_dec_init failed, ret="
86 << status;
87 delete vpx_codec_;
88 vpx_codec_ = NULL;
89 }
90
91 is_initialized_ = true;
92 return true;
93 }
94
95 void LibvpxCdmVideoDecoder::Deinitialize() {
96 DVLOG(1) << "Deinitialize()";
97
98 if (vpx_codec_) {
99 vpx_codec_destroy(vpx_codec_);
100 vpx_codec_ = NULL;
101 }
102
103 is_initialized_ = false;
104 }
105
106 void LibvpxCdmVideoDecoder::Reset() {
107 DVLOG(1) << "Reset()";
108 }
109
110 // static
111 bool LibvpxCdmVideoDecoder::IsValidOutputConfig(cdm::VideoFormat format,
112 const cdm::Size& data_size) {
113 return ((format == cdm::kYv12 || format == cdm::kI420) &&
114 (data_size.width % 2) == 0 && (data_size.height % 2) == 0 &&
115 data_size.width > 0 && data_size.height > 0 &&
116 data_size.width <= media::limits::kMaxDimension &&
117 data_size.height <= media::limits::kMaxDimension &&
118 data_size.width * data_size.height <= media::limits::kMaxCanvas);
119 }
120
121 cdm::Status LibvpxCdmVideoDecoder::DecodeFrame(
122 const uint8_t* compressed_frame,
123 int32_t compressed_frame_size,
124 int64_t timestamp,
125 cdm::VideoFrame* decoded_frame) {
126 DVLOG(1) << "DecodeFrame()";
127 DCHECK(decoded_frame);
128
129 // Pass |compressed_frame| to libvpx.
130 void* user_priv = reinterpret_cast<void*>(&timestamp);
131 vpx_codec_err_t status = vpx_codec_decode(vpx_codec_,
132 compressed_frame,
133 compressed_frame_size,
134 user_priv,
135 0);
136 if (status != VPX_CODEC_OK) {
137 LOG(ERROR) << "DecodeFrameLibvpx(): vpx_codec_decode failed, status="
138 << status;
139 return cdm::kDecodeError;
140 }
141
142 // Gets pointer to decoded data.
143 vpx_codec_iter_t iter = NULL;
144 vpx_image_ = vpx_codec_get_frame(vpx_codec_, &iter);
145 if (!vpx_image_)
146 return cdm::kNeedMoreData;
147
148 if (vpx_image_->user_priv != reinterpret_cast<void*>(&timestamp)) {
149 LOG(ERROR) << "DecodeFrameLibvpx() invalid output timestamp.";
150 return cdm::kDecodeError;
151 }
152 decoded_frame->set_timestamp(timestamp);
153
154 if (!CopyVpxImageTo(decoded_frame)) {
155 LOG(ERROR) << "DecodeFrameLibvpx() could not copy vpx image to output "
156 << "buffer.";
157 return cdm::kDecodeError;
158 }
159
160 return cdm::kSuccess;
161
162 }
163
164 bool LibvpxCdmVideoDecoder::CopyVpxImageTo(cdm::VideoFrame* cdm_video_frame) {
165 DCHECK(cdm_video_frame);
166 DCHECK_EQ(vpx_image_->fmt, VPX_IMG_FMT_I420);
167 DCHECK_EQ(vpx_image_->d_w % 2, 0U);
168 DCHECK_EQ(vpx_image_->d_h % 2, 0U);
169
170 #if defined(USE_COPYPLANE_WITH_LIBVPX)
171 const int y_size = vpx_image_->d_w * vpx_image_->d_h;
172 const int uv_size = y_size / 2;
173 const int space_required = y_size + (uv_size * 2);
174
175 DCHECK(!cdm_video_frame->frame_buffer());
176 cdm_video_frame->set_frame_buffer(allocator_->Allocate(space_required));
177 if (!cdm_video_frame->frame_buffer()) {
178 LOG(ERROR) << "CopyVpxImageTo() cdm::Allocator::Allocate failed.";
179 return false;
180 }
181
182 CopyPlane(vpx_image_->planes[VPX_PLANE_Y],
183 vpx_image_->stride[VPX_PLANE_Y],
184 vpx_image_->d_w,
185 vpx_image_->d_h,
186 vpx_image_->d_w,
187 cdm_video_frame->frame_buffer()->data());
188
189 const int uv_stride = vpx_image_->d_w / 2;
190 const int uv_rows = vpx_image_->d_h / 2;
191 CopyPlane(vpx_image_->planes[VPX_PLANE_U],
192 vpx_image_->stride[VPX_PLANE_U],
193 uv_stride,
194 uv_rows,
195 uv_stride,
196 cdm_video_frame->frame_buffer()->data() + y_size);
197
198 CopyPlane(vpx_image_->planes[VPX_PLANE_V],
199 vpx_image_->stride[VPX_PLANE_V],
200 uv_stride,
201 uv_rows,
202 uv_stride,
203 cdm_video_frame->frame_buffer()->data() + y_size + uv_size);
204
205 cdm_video_frame->set_format(cdm::kYv12);
206
207 cdm::Size video_frame_size;
208 video_frame_size.width = vpx_image_->d_w;
209 video_frame_size.height = vpx_image_->d_h;
210 cdm_video_frame->set_size(video_frame_size);
211
212 cdm_video_frame->set_plane_offset(cdm::VideoFrame::kYPlane, 0);
213 cdm_video_frame->set_plane_offset(cdm::VideoFrame::kUPlane, y_size);
214 cdm_video_frame->set_plane_offset(cdm::VideoFrame::kVPlane,
215 y_size + uv_size);
216
217 cdm_video_frame->set_stride(cdm::VideoFrame::kYPlane, vpx_image_->d_w);
218 cdm_video_frame->set_stride(cdm::VideoFrame::kUPlane, uv_stride);
219 cdm_video_frame->set_stride(cdm::VideoFrame::kVPlane, uv_stride);
220 #else
221 const int y_size = vpx_image_->stride[VPX_PLANE_Y] * vpx_image_->d_h;
222 const int uv_rows = vpx_image_->d_h / 2;
223 const int u_size = vpx_image_->stride[VPX_PLANE_U] * uv_rows;
224 const int v_size = vpx_image_->stride[VPX_PLANE_V] * uv_rows;
225 const int space_required = y_size + u_size + v_size;
226
227 DCHECK(!cdm_video_frame->frame_buffer());
228 cdm_video_frame->set_frame_buffer(allocator_->Allocate(space_required));
229 if (!cdm_video_frame->frame_buffer()) {
230 LOG(ERROR) << "CopyVpxImageTo() cdm::Allocator::Allocate failed.";
231 return false;
232 }
233
234 memcpy(cdm_video_frame->frame_buffer()->data(),
235 vpx_image_->planes[VPX_PLANE_Y],
236 y_size);
237 memcpy(cdm_video_frame->frame_buffer()->data() + y_size,
238 vpx_image_->planes[VPX_PLANE_U],
239 u_size);
240 memcpy(cdm_video_frame->frame_buffer()->data() + y_size + u_size,
241 vpx_image_->planes[VPX_PLANE_V],
242 v_size);
243
244 cdm_video_frame->set_format(cdm::kYv12);
245
246 cdm::Size video_frame_size;
247 video_frame_size.width = vpx_image_->d_w;
248 video_frame_size.height = vpx_image_->d_h;
249 cdm_video_frame->set_size(video_frame_size);
250
251 cdm_video_frame->set_plane_offset(cdm::VideoFrame::kYPlane, 0);
252 cdm_video_frame->set_plane_offset(cdm::VideoFrame::kUPlane, y_size);
253 cdm_video_frame->set_plane_offset(cdm::VideoFrame::kVPlane,
254 y_size + u_size);
255
256 cdm_video_frame->set_stride(cdm::VideoFrame::kYPlane,
257 vpx_image_->stride[VPX_PLANE_Y]);
258 cdm_video_frame->set_stride(cdm::VideoFrame::kUPlane,
259 vpx_image_->stride[VPX_PLANE_U]);
260 cdm_video_frame->set_stride(cdm::VideoFrame::kVPlane,
261 vpx_image_->stride[VPX_PLANE_V]);
262 #endif // USE_COPYPLANE_WITH_LIBVPX
263
264 return true;
265 }
266
267 } // namespace webkit_media
OLDNEW
« no previous file with comments | « webkit/media/crypto/ppapi/libvpx_cdm_video_decoder.h ('k') | webkit/media/webkit_media.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698