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