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
24VideoDecoderVP8::VideoDecoderVP8(const char *mimeType)
25    : VideoDecoderBase(mimeType, VBP_VP8) {
26    invalidateReferenceFrames(0);
27    invalidateReferenceFrames(1);
28}
29
30VideoDecoderVP8::~VideoDecoderVP8() {
31    stop();
32}
33
34void 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
43void 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
50void 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
107Decode_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
120Decode_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
147void VideoDecoderVP8::stop(void) {
148    VideoDecoderBase::stop();
149
150    invalidateReferenceFrames(0);
151    invalidateReferenceFrames(1);
152}
153
154void VideoDecoderVP8::flush(void) {
155    VideoDecoderBase::flush();
156
157    invalidateReferenceFrames(0);
158    invalidateReferenceFrames(1);
159}
160
161Decode_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
195Decode_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
271Decode_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
360Decode_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
391void 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
416void 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
429void 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
454void 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
480Decode_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