• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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