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

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

Powered by Google App Engine
This is Rietveld 408576698