1 /*
2 * Copyright (c) 2009-2011 Intel Corporation. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "VideoDecoderVP8.h"
18 #include "VideoDecoderTrace.h"
19 #include <string.h>
20
21 #define MAX_PICTURE_WIDTH_VP8 1920
22 #define MAX_PICTURE_HEIGHT_VP8 1088
23
VideoDecoderVP8(const char * mimeType)24 VideoDecoderVP8::VideoDecoderVP8(const char *mimeType)
25 : VideoDecoderBase(mimeType, VBP_VP8) {
26 invalidateReferenceFrames(0);
27 invalidateReferenceFrames(1);
28 }
29
~VideoDecoderVP8()30 VideoDecoderVP8::~VideoDecoderVP8() {
31 stop();
32 }
33
invalidateReferenceFrames(int toggle)34 void VideoDecoderVP8::invalidateReferenceFrames(int toggle) {
35 ReferenceFrameBuffer *p = mRFBs[toggle];
36 for (int i = 0; i < VP8_REF_SIZE; i++) {
37 p->index = (uint32_t) -1;
38 p->surfaceBuffer = NULL;
39 p++;
40 }
41 }
42
clearAsReference(int toggle,int ref_type)43 void VideoDecoderVP8::clearAsReference(int toggle, int ref_type) {
44 ReferenceFrameBuffer ref = mRFBs[toggle][ref_type];
45 if (ref.surfaceBuffer) {
46 ref.surfaceBuffer->asReferernce = false;
47 }
48 }
49
updateFormatInfo(vbp_data_vp8 * data)50 void VideoDecoderVP8::updateFormatInfo(vbp_data_vp8 *data) {
51 uint32_t width = data->codec_data->frame_width;
52 uint32_t height = data->codec_data->frame_height;
53 ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d",
54 mVideoFormatInfo.width, mVideoFormatInfo.height, width, height);
55
56 if ((mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER) && mStoreMetaData) {
57 pthread_mutex_lock(&mFormatLock);
58 }
59
60 if ((mVideoFormatInfo.width != width ||
61 mVideoFormatInfo.height != height) &&
62 width && height) {
63 if ((VideoDecoderBase::alignMB(mVideoFormatInfo.width) != width) ||
64 (VideoDecoderBase::alignMB(mVideoFormatInfo.height) != height)) {
65 mSizeChanged = true;
66 ITRACE("Video size is changed.");
67 }
68 mVideoFormatInfo.width = width;
69 mVideoFormatInfo.height = height;
70 }
71
72 // video_range has default value of 0. Y ranges from 16 to 235.
73 mVideoFormatInfo.videoRange = 0;
74
75 switch (data->codec_data->clr_type) {
76 case 0:
77 mVideoFormatInfo.colorMatrix = VA_SRC_BT601;
78 break;
79 case 1:
80 default:
81 mVideoFormatInfo.colorMatrix = 0;
82 break;
83 }
84
85 mVideoFormatInfo.cropLeft = data->codec_data->crop_left;
86 mVideoFormatInfo.cropRight = data->codec_data->crop_right;
87 mVideoFormatInfo.cropTop = data->codec_data->crop_top;
88 mVideoFormatInfo.cropBottom = data->codec_data->crop_bottom;
89 ITRACE("Cropping: left = %d, top = %d, right = %d, bottom = %d", data->codec_data->crop_left, data->codec_data->crop_top, data->codec_data->crop_right, data->codec_data->crop_bottom);
90
91 if ((mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER) && mStoreMetaData) {
92 if (mSizeChanged) {
93 mVideoFormatInfo.valid = false;
94 } else {
95 mVideoFormatInfo.valid = true;
96 }
97
98 pthread_mutex_unlock(&mFormatLock);
99 } else {
100 mVideoFormatInfo.valid = true;
101 }
102
103 setRenderRect();
104 setColorSpaceInfo(mVideoFormatInfo.colorMatrix, mVideoFormatInfo.videoRange);
105 }
106
startVA(vbp_data_vp8 * data)107 Decode_Status VideoDecoderVP8::startVA(vbp_data_vp8 *data) {
108 updateFormatInfo(data);
109
110 VAProfile vaProfile = VAProfileVP8Version0_3;
111 if (data->codec_data->version_num > 3) {
112 return DECODE_PARSER_FAIL;
113 }
114
115 enableLowDelayMode(true);
116
117 return VideoDecoderBase::setupVA(VP8_SURFACE_NUMBER + VP8_REF_SIZE, vaProfile);
118 }
119
start(VideoConfigBuffer * buffer)120 Decode_Status VideoDecoderVP8::start(VideoConfigBuffer *buffer) {
121 Decode_Status status;
122
123 status = VideoDecoderBase::start(buffer);
124 CHECK_STATUS("VideoDecoderBase::start");
125
126 // We don't want base class to manage reference.
127 VideoDecoderBase::ManageReference(false);
128
129 if (buffer->data == NULL || buffer->size == 0) {
130 WTRACE("No config data to start VA.");
131 return DECODE_SUCCESS;
132 }
133
134 vbp_data_vp8 *data = NULL;
135 status = VideoDecoderBase::parseBuffer(buffer->data, buffer->size, true, (void**)&data);
136 CHECK_STATUS("VideoDecoderBase::parseBuffer");
137
138 if (data->codec_data->frame_width > MAX_PICTURE_WIDTH_VP8 ||
139 data->codec_data->frame_height > MAX_PICTURE_HEIGHT_VP8) {
140 return DECODE_INVALID_DATA;
141 }
142
143 status = startVA(data);
144 return status;
145 }
146
stop(void)147 void VideoDecoderVP8::stop(void) {
148 VideoDecoderBase::stop();
149
150 invalidateReferenceFrames(0);
151 invalidateReferenceFrames(1);
152 }
153
flush(void)154 void VideoDecoderVP8::flush(void) {
155 VideoDecoderBase::flush();
156
157 invalidateReferenceFrames(0);
158 invalidateReferenceFrames(1);
159 }
160
decode(VideoDecodeBuffer * buffer)161 Decode_Status VideoDecoderVP8::decode(VideoDecodeBuffer *buffer) {
162 Decode_Status status;
163 vbp_data_vp8 *data = NULL;
164 if (buffer == NULL) {
165 ETRACE("VideoDecodeBuffer is NULL.");
166 return DECODE_INVALID_DATA;
167 }
168
169 status = VideoDecoderBase::parseBuffer(
170 buffer->data,
171 buffer->size,
172 false,
173 (void**)&data);
174 CHECK_STATUS("VideoDecoderBase::parseBuffer");
175
176 if (data->codec_data->frame_width > MAX_PICTURE_WIDTH_VP8 ||
177 data->codec_data->frame_height > MAX_PICTURE_HEIGHT_VP8) {
178 return DECODE_INVALID_DATA;
179 }
180
181 mShowFrame = data->codec_data->show_frame;
182
183 if (!mVAStarted) {
184 status = startVA(data);
185 CHECK_STATUS("startVA");
186 }
187
188 VideoDecoderBase::setRotationDegrees(buffer->rotationDegrees);
189
190 status = decodeFrame(buffer, data);
191
192 return status;
193 }
194
decodeFrame(VideoDecodeBuffer * buffer,vbp_data_vp8 * data)195 Decode_Status VideoDecoderVP8::decodeFrame(VideoDecodeBuffer* buffer, vbp_data_vp8 *data) {
196 Decode_Status status;
197 bool useGraphicbuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
198 mCurrentPTS = buffer->timeStamp;
199 if (0 == data->num_pictures || NULL == data->pic_data) {
200 WTRACE("Number of pictures is 0.");
201 return DECODE_SUCCESS;
202 }
203
204 if (VP8_KEY_FRAME == data->codec_data->frame_type) {
205 updateFormatInfo(data);
206 if (mSizeChanged && !(mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER)) {
207 mSizeChanged = false;
208 return DECODE_FORMAT_CHANGE;
209 }
210
211 bool needFlush = false;
212 if (useGraphicbuffer) {
213 // For VP8 in adaptive playback legacy mode,
214 // force buffer reallocation.
215 needFlush = mSizeChanged;
216 }
217 if (needFlush) {
218 if (mStoreMetaData) {
219 status = endDecodingFrame(false);
220 CHECK_STATUS("endDecodingFrame");
221 } else {
222 flushSurfaceBuffers();
223 }
224 mSizeChanged = false;
225 return DECODE_FORMAT_CHANGE;
226 }
227 }
228
229 if (data->codec_data->frame_type == VP8_SKIPPED_FRAME) {
230 // Do nothing for skip frame as the last frame will be rendered agian by natively
231 return DECODE_SUCCESS;
232 }
233
234 status = acquireSurfaceBuffer();
235 CHECK_STATUS("acquireSurfaceBuffer");
236
237 // set referenceFrame to true if frame decoded is I/P frame, false otherwise.
238 int frameType = data->codec_data->frame_type;
239 mAcquiredBuffer->referenceFrame = (frameType == VP8_KEY_FRAME || frameType == VP8_INTER_FRAME);
240 // assume it is frame picture.
241 mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
242 mAcquiredBuffer->renderBuffer.timeStamp = buffer->timeStamp;
243 mAcquiredBuffer->renderBuffer.flag = 0;
244 if (buffer->flag & WANT_DECODE_ONLY) {
245 mAcquiredBuffer->renderBuffer.flag |= WANT_DECODE_ONLY;
246 }
247 if (mSizeChanged) {
248 mSizeChanged = false;
249 mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE;
250 }
251
252 // Here data->num_pictures is always equal to 1
253 for (uint32_t index = 0; index < data->num_pictures; index++) {
254 status = decodePicture(data, index);
255 if (status != DECODE_SUCCESS) {
256 endDecodingFrame(true);
257 return status;
258 }
259 }
260
261 if (frameType != VP8_SKIPPED_FRAME) {
262 updateReferenceFrames(data);
263 }
264
265 // if sample is successfully decoded, call outputSurfaceBuffer(); otherwise
266 // call releaseSurfacebuffer();
267 status = outputSurfaceBuffer();
268 return status;
269 }
270
decodePicture(vbp_data_vp8 * data,int32_t picIndex)271 Decode_Status VideoDecoderVP8::decodePicture(vbp_data_vp8 *data, int32_t picIndex) {
272 VAStatus vaStatus = VA_STATUS_SUCCESS;
273 Decode_Status status;
274 uint32_t bufferIDCount = 0;
275 VABufferID bufferIDs[5];
276
277 vbp_picture_data_vp8 *picData = &(data->pic_data[picIndex]);
278 VAPictureParameterBufferVP8 *picParams = picData->pic_parms;
279
280 status = setReference(picParams);
281 CHECK_STATUS("setReference");
282
283 vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
284 CHECK_VA_STATUS("vaBeginPicture");
285 // setting mDecodingFrame to true so vaEndPicture will be invoked to end the picture decoding.
286 mDecodingFrame = true;
287
288 vaStatus = vaCreateBuffer(
289 mVADisplay,
290 mVAContext,
291 VAPictureParameterBufferType,
292 sizeof(VAPictureParameterBufferVP8),
293 1,
294 picParams,
295 &bufferIDs[bufferIDCount]);
296 CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
297 bufferIDCount++;
298
299 vaStatus = vaCreateBuffer(
300 mVADisplay,
301 mVAContext,
302 VAProbabilityBufferType,
303 sizeof(VAProbabilityDataBufferVP8),
304 1,
305 data->prob_data,
306 &bufferIDs[bufferIDCount]);
307 CHECK_VA_STATUS("vaCreateProbabilityBuffer");
308 bufferIDCount++;
309
310 vaStatus = vaCreateBuffer(
311 mVADisplay,
312 mVAContext,
313 VAIQMatrixBufferType,
314 sizeof(VAIQMatrixBufferVP8),
315 1,
316 data->IQ_matrix_buf,
317 &bufferIDs[bufferIDCount]);
318 CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
319 bufferIDCount++;
320
321 /* Here picData->num_slices is always equal to 1 */
322 for (uint32_t i = 0; i < picData->num_slices; i++) {
323 vaStatus = vaCreateBuffer(
324 mVADisplay,
325 mVAContext,
326 VASliceParameterBufferType,
327 sizeof(VASliceParameterBufferVP8),
328 1,
329 &(picData->slc_data[i].slc_parms),
330 &bufferIDs[bufferIDCount]);
331 CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
332 bufferIDCount++;
333
334 vaStatus = vaCreateBuffer(
335 mVADisplay,
336 mVAContext,
337 VASliceDataBufferType,
338 picData->slc_data[i].slice_size, //size
339 1, //num_elements
340 picData->slc_data[i].buffer_addr + picData->slc_data[i].slice_offset,
341 &bufferIDs[bufferIDCount]);
342 CHECK_VA_STATUS("vaCreateSliceDataBuffer");
343 bufferIDCount++;
344 }
345
346 vaStatus = vaRenderPicture(
347 mVADisplay,
348 mVAContext,
349 bufferIDs,
350 bufferIDCount);
351 CHECK_VA_STATUS("vaRenderPicture");
352
353 vaStatus = vaEndPicture(mVADisplay, mVAContext);
354 mDecodingFrame = false;
355 CHECK_VA_STATUS("vaEndPicture");
356
357 return DECODE_SUCCESS;
358 }
359
setReference(VAPictureParameterBufferVP8 * picParam)360 Decode_Status VideoDecoderVP8::setReference(VAPictureParameterBufferVP8 *picParam) {
361 int frameType = picParam->pic_fields.bits.key_frame;
362 switch (frameType) {
363 case VP8_KEY_FRAME:
364 picParam->last_ref_frame = VA_INVALID_SURFACE;
365 picParam->alt_ref_frame = VA_INVALID_SURFACE;
366 picParam->golden_ref_frame = VA_INVALID_SURFACE;
367 break;
368 case VP8_INTER_FRAME:
369 if (mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer == NULL ||
370 mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer == NULL ||
371 mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer == NULL) {
372 mAcquiredBuffer->renderBuffer.errBuf.errorNumber = 1;
373 mAcquiredBuffer->renderBuffer.errBuf.errorArray[0].type = DecodeRefMissing;
374 return DECODE_NO_REFERENCE;
375 }
376 //mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer = mLastReference;
377 picParam->last_ref_frame = mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer->renderBuffer.surface;
378 picParam->alt_ref_frame = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer->renderBuffer.surface;
379 picParam->golden_ref_frame = mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer->renderBuffer.surface;
380 break;
381 case VP8_SKIPPED_FRAME:
382 // will never happen here
383 break;
384 default:
385 return DECODE_PARSER_FAIL;
386 }
387
388 return DECODE_SUCCESS;
389 }
390
updateReferenceFrames(vbp_data_vp8 * data)391 void VideoDecoderVP8::updateReferenceFrames(vbp_data_vp8 *data) {
392 /* Refresh last frame reference buffer using the currently reconstructed frame */
393 refreshLastReference(data);
394
395 /* Refresh golden frame reference buffer using the currently reconstructed frame */
396 refreshGoldenReference(data);
397
398 /* Refresh alternative frame reference buffer using the currently reconstructed frame */
399 refreshAltReference(data);
400
401 /* Update reference frames */
402 for (int i = 0; i < VP8_REF_SIZE; i++) {
403 VideoSurfaceBuffer *p = mRFBs[1][i].surfaceBuffer;
404 int j;
405 for (j = 0; j < VP8_REF_SIZE; j++) {
406 if (p == mRFBs[0][j].surfaceBuffer) {
407 break;
408 }
409 }
410 if (j == VP8_REF_SIZE) {
411 clearAsReference(1, i);
412 }
413 }
414 }
415
refreshLastReference(vbp_data_vp8 * data)416 void VideoDecoderVP8::refreshLastReference(vbp_data_vp8 *data) {
417 /* Save previous last reference */
418 mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer = mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer;
419 mRFBs[1][VP8_LAST_REF_PIC].index = mRFBs[0][VP8_LAST_REF_PIC].index;
420
421 /* For key frame, this is always true */
422 if (data->codec_data->refresh_last_frame) {
423 mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer = mAcquiredBuffer;
424 mRFBs[0][VP8_LAST_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface;
425 mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer->asReferernce = true;
426 }
427 }
428
refreshGoldenReference(vbp_data_vp8 * data)429 void VideoDecoderVP8::refreshGoldenReference(vbp_data_vp8 *data) {
430 /* Save previous golden reference */
431 mRFBs[1][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer;
432 mRFBs[1][VP8_GOLDEN_REF_PIC].index = mRFBs[0][VP8_GOLDEN_REF_PIC].index;
433
434 if (data->codec_data->golden_copied != BufferCopied_NoneToGolden) {
435 if (data->codec_data->golden_copied == BufferCopied_LastToGolden) {
436 /* LastFrame is copied to GoldenFrame */
437 mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer;
438 mRFBs[0][VP8_GOLDEN_REF_PIC].index = mRFBs[1][VP8_LAST_REF_PIC].index;
439 } else if (data->codec_data->golden_copied == BufferCopied_AltRefToGolden) {
440 /* AltRefFrame is copied to GoldenFrame */
441 mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer;
442 mRFBs[0][VP8_GOLDEN_REF_PIC].index = mRFBs[0][VP8_ALT_REF_PIC].index;
443 }
444 }
445
446 /* For key frame, this is always true */
447 if (data->codec_data->refresh_golden_frame) {
448 mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mAcquiredBuffer;
449 mRFBs[0][VP8_GOLDEN_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface;
450 mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer->asReferernce = true;
451 }
452 }
453
refreshAltReference(vbp_data_vp8 * data)454 void VideoDecoderVP8::refreshAltReference(vbp_data_vp8 *data) {
455 /* Save previous alternative reference */
456 mRFBs[1][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer;
457 mRFBs[1][VP8_ALT_REF_PIC].index = mRFBs[0][VP8_ALT_REF_PIC].index;
458
459 if (data->codec_data->altref_copied != BufferCopied_NoneToAltRef) {
460 if (data->codec_data->altref_copied == BufferCopied_LastToAltRef) {
461 /* LastFrame is copied to AltRefFrame */
462 mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer;
463 mRFBs[0][VP8_ALT_REF_PIC].index = mRFBs[1][VP8_LAST_REF_PIC].index;
464 } else if (data->codec_data->altref_copied == BufferCopied_GoldenToAltRef) {
465 /* GoldenFrame is copied to AltRefFrame */
466 mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[1][VP8_GOLDEN_REF_PIC].surfaceBuffer;
467 mRFBs[0][VP8_ALT_REF_PIC].index = mRFBs[1][VP8_GOLDEN_REF_PIC].index;
468 }
469 }
470
471 /* For key frame, this is always true */
472 if (data->codec_data->refresh_alt_frame) {
473 mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mAcquiredBuffer;
474 mRFBs[0][VP8_ALT_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface;
475 mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer->asReferernce = true;
476 }
477 }
478
479
checkHardwareCapability()480 Decode_Status VideoDecoderVP8::checkHardwareCapability() {
481 VAStatus vaStatus;
482 VAConfigAttrib cfgAttribs[2];
483 cfgAttribs[0].type = VAConfigAttribMaxPictureWidth;
484 cfgAttribs[1].type = VAConfigAttribMaxPictureHeight;
485 vaStatus = vaGetConfigAttributes(mVADisplay, VAProfileVP8Version0_3,
486 VAEntrypointVLD, cfgAttribs, 2);
487 CHECK_VA_STATUS("vaGetConfigAttributes");
488 if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) {
489 ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d",
490 cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height);
491 return DECODE_DRIVER_FAIL;
492 }
493
494 return DECODE_SUCCESS;
495 }
496
497