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