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 "VideoDecoderWMV.h"
18#include "VideoDecoderTrace.h"
19#include <string.h>
20
21VideoDecoderWMV::VideoDecoderWMV(const char *mimeType)
22    : VideoDecoderBase(mimeType, VBP_VC1),
23      mBufferIDs(NULL),
24      mNumBufferIDs(0),
25      mConfigDataParsed(false),
26      mRangeMapped(false),
27      mDeblockedCurrPicIndex(0),
28      mDeblockedLastPicIndex(1),
29      mDeblockedForwardPicIndex(2) {
30}
31
32
33VideoDecoderWMV::~VideoDecoderWMV() {
34    stop();
35}
36
37Decode_Status VideoDecoderWMV::start(VideoConfigBuffer *buffer) {
38    Decode_Status status;
39
40    status = VideoDecoderBase::start(buffer);
41    CHECK_STATUS("VideoDecoderBase::start");
42
43    if (buffer->data == NULL || buffer->size == 0) {
44        WTRACE("No config data to start VA.");
45        return DECODE_SUCCESS;
46    }
47
48    vbp_data_vc1 *data = NULL;
49    status = parseBuffer(buffer->data, buffer->size, &data);
50    CHECK_STATUS("parseBuffer");
51
52    status = startVA(data);
53    return status;
54}
55
56void VideoDecoderWMV::stop(void) {
57    if (mBufferIDs) {
58        delete [] mBufferIDs;
59        mBufferIDs = NULL;
60    }
61    mNumBufferIDs = 0;
62    mConfigDataParsed = false;
63    mRangeMapped = false;
64
65    mDeblockedCurrPicIndex = 0;
66    mDeblockedLastPicIndex = 1;
67    mDeblockedForwardPicIndex = 2;
68
69    VideoDecoderBase::stop();
70}
71
72void VideoDecoderWMV::flush(void) {
73    VideoDecoderBase::flush();
74
75    mRangeMapped = false;
76    mDeblockedCurrPicIndex = 0;
77    mDeblockedLastPicIndex = 1;
78    mDeblockedForwardPicIndex = 2;
79}
80
81Decode_Status VideoDecoderWMV::decode(VideoDecodeBuffer *buffer) {
82    Decode_Status status;
83    vbp_data_vc1 *data = NULL;
84    bool useGraphicbuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
85    if (buffer == NULL) {
86        return DECODE_INVALID_DATA;
87    }
88
89    status = parseBuffer(buffer->data, buffer->size, &data);
90    CHECK_STATUS("parseBuffer");
91
92    if (!mVAStarted) {
93        status = startVA(data);
94        CHECK_STATUS("startVA");
95    }
96
97    if (mSizeChanged && !useGraphicbuffer) {
98        mSizeChanged = false;
99        return DECODE_FORMAT_CHANGE;
100    }
101
102    if ((mVideoFormatInfo.width != data->se_data->CODED_WIDTH ||
103        mVideoFormatInfo.height != data->se_data->CODED_HEIGHT) &&
104        data->se_data->CODED_WIDTH &&
105        data->se_data->CODED_HEIGHT) {
106        ITRACE("video size is changed from %dx%d to %dx%d", mVideoFormatInfo.width, mVideoFormatInfo.height,
107                data->se_data->CODED_WIDTH, data->se_data->CODED_HEIGHT);
108        mVideoFormatInfo.width = data->se_data->CODED_WIDTH;
109        mVideoFormatInfo.height = data->se_data->CODED_HEIGHT;
110        bool noNeedFlush = false;
111        if (useGraphicbuffer) {
112            noNeedFlush = (mVideoFormatInfo.width <= mVideoFormatInfo.surfaceWidth)
113                    && (mVideoFormatInfo.height <= mVideoFormatInfo.surfaceHeight);
114        }
115
116        setRenderRect();
117
118        if (noNeedFlush) {
119            mSizeChanged = true;
120        } else {
121            flushSurfaceBuffers();
122            mSizeChanged = false;
123            return DECODE_FORMAT_CHANGE;
124        }
125    }
126
127    status = decodeFrame(buffer, data);
128    CHECK_STATUS("decodeFrame");
129    return status;
130}
131
132Decode_Status VideoDecoderWMV::decodeFrame(VideoDecodeBuffer* buffer, vbp_data_vc1 *data) {
133    Decode_Status status;
134    mCurrentPTS = buffer->timeStamp;
135    if (0 == data->num_pictures || NULL == data->pic_data) {
136        WTRACE("Number of pictures is 0, buffer contains configuration data only?");
137        return DECODE_SUCCESS;
138    }
139
140    if (data->pic_data[0].picture_is_skipped == VC1_PTYPE_SKIPPED) {
141
142        // Do nothing for skip frame as the last frame will be rendered agian by natively
143        // No needs to handle reference frame neither
144        return DECODE_SUCCESS;
145#if 0
146        //use the last P or I frame surface for skipped frame and treat it as P frame
147        if (mLastReference == NULL) {
148            // TODO: handle this case
149            WTRACE("The last reference is unavailable to construct skipped frame.");
150            return DECODE_SUCCESS;
151        }
152
153        status = acquireSurfaceBuffer();
154        CHECK_STATUS("acquireSurfaceBuffer");
155        mAcquiredBuffer->renderBuffer.timeStamp = mCurrentPTS;
156        mAcquiredBuffer->renderBuffer.flag = 0;
157        mAcquiredBuffer->renderBuffer.scanFormat = mLastReference->renderBuffer.scanFormat;
158        mAcquiredBuffer->renderBuffer.surface = mLastReference->renderBuffer.surface;
159        // No need to update mappedData for HW decoding
160        //mAcquiredBuffer->mappedData.data = mLastReference->mappedData.data;
161        mAcquiredBuffer->referenceFrame = true;
162        // let outputSurfaceBuffer handle "asReference" for VC1
163        status = outputSurfaceBuffer();
164        return status;
165#endif
166    }
167
168    status = acquireSurfaceBuffer();
169    CHECK_STATUS("acquireSurfaceBuffer");
170
171    mAcquiredBuffer->renderBuffer.timeStamp = buffer->timeStamp;
172    if (buffer->flag & HAS_DISCONTINUITY) {
173        mAcquiredBuffer->renderBuffer.flag |= HAS_DISCONTINUITY;
174    }
175    if (buffer->flag & WANT_DECODE_ONLY) {
176        mAcquiredBuffer->renderBuffer.flag |= WANT_DECODE_ONLY;
177    }
178    if (mSizeChanged) {
179        mSizeChanged = false;
180        mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE;
181    }
182
183    if (data->num_pictures > 1) {
184        if (data->pic_data[0].pic_parms->picture_fields.bits.is_first_field) {
185            mAcquiredBuffer->renderBuffer.scanFormat = VA_TOP_FIELD;
186        } else {
187            mAcquiredBuffer->renderBuffer.scanFormat = VA_BOTTOM_FIELD;
188        }
189    } else {
190        mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
191    }
192
193    mRangeMapped = (data->se_data->RANGE_MAPY_FLAG || data->se_data->RANGE_MAPUV_FLAG || data->se_data->RANGERED);
194
195    int frameType = data->pic_data[0].pic_parms->picture_fields.bits.picture_type;
196    mAcquiredBuffer->referenceFrame = (frameType == VC1_PTYPE_I || frameType == VC1_PTYPE_P);
197
198    // TODO: handle multiple frames parsed from a sample buffer
199    int numPictures = (data->num_pictures > 1) ? 2 : 1;
200
201    for (int index = 0; index < numPictures; index++) {
202        status = decodePicture(data, index);
203        if (status != DECODE_SUCCESS) {
204            endDecodingFrame(true);
205            return status;
206        }
207    }
208
209    if (mRangeMapped) {
210        updateDeblockedPicIndexes(frameType);
211    }
212
213    // let outputSurfaceBuffer handle "asReference" for VC1
214    status = outputSurfaceBuffer();
215    return status;
216}
217
218
219Decode_Status VideoDecoderWMV::decodePicture(vbp_data_vc1 *data, int32_t picIndex) {
220    VAStatus vaStatus = VA_STATUS_SUCCESS;
221    Decode_Status status;
222    int32_t bufferIDCount = 0;
223    vbp_picture_data_vc1 *picData = &(data->pic_data[picIndex]);
224    VAPictureParameterBufferVC1 *picParams = picData->pic_parms;
225
226    if (picParams == NULL) {
227        return DECODE_PARSER_FAIL;
228    }
229
230    status = allocateVABufferIDs(picData->num_slices * 2 + 2);
231    CHECK_STATUS("allocateVABufferIDs");
232
233    status = setReference(picParams, picIndex, mAcquiredBuffer->renderBuffer.surface);
234    CHECK_STATUS("setReference");
235
236    if (mRangeMapped) {
237        // keep the destination surface for the picture after decoding and in-loop filtering
238        picParams->inloop_decoded_picture = mExtraSurfaces[mDeblockedCurrPicIndex];
239    } else {
240        picParams->inloop_decoded_picture = VA_INVALID_SURFACE;
241    }
242
243    vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
244    CHECK_VA_STATUS("vaBeginPicture");
245    // setting mDecodingFrame to true so vaEndPicture will be invoked to end the picture decoding.
246    mDecodingFrame = true;
247
248    vaStatus = vaCreateBuffer(
249            mVADisplay,
250            mVAContext,
251            VAPictureParameterBufferType,
252            sizeof(VAPictureParameterBufferVC1),
253            1,
254            picParams,
255            &mBufferIDs[bufferIDCount]);
256    CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
257    bufferIDCount++;
258
259    if (picParams->bitplane_present.value) {
260        vaStatus = vaCreateBuffer(
261                mVADisplay,
262                mVAContext,
263                VABitPlaneBufferType,
264                picData->size_bitplanes,
265                1,
266                picData->packed_bitplanes,
267                &mBufferIDs[bufferIDCount]);
268        CHECK_VA_STATUS("vaCreateBitPlaneBuffer");
269        bufferIDCount++;
270    }
271
272    for (uint32_t i = 0; i < picData->num_slices; i++) {
273        vaStatus = vaCreateBuffer(
274                mVADisplay,
275                mVAContext,
276                VASliceParameterBufferType,
277                sizeof(VASliceParameterBufferVC1),
278                1,
279                &(picData->slc_data[i].slc_parms),
280                &mBufferIDs[bufferIDCount]);
281        CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
282        bufferIDCount++;
283
284        vaStatus = vaCreateBuffer(
285                mVADisplay,
286                mVAContext,
287                VASliceDataBufferType,
288                //size
289                picData->slc_data[i].slice_size,
290                //num_elements
291                1,
292                //slice data buffer pointer
293                //Note that this is the original data buffer ptr;
294                // offset to the actual slice data is provided in
295                // slice_data_offset in VASliceParameterBufferVC1
296                picData->slc_data[i].buffer_addr + picData->slc_data[i].slice_offset,
297                &mBufferIDs[bufferIDCount]);
298        CHECK_VA_STATUS("vaCreateSliceDataBuffer");
299        bufferIDCount++;
300    }
301
302    vaStatus = vaRenderPicture(
303            mVADisplay,
304            mVAContext,
305            mBufferIDs,
306            bufferIDCount);
307    CHECK_VA_STATUS("vaRenderPicture");
308
309    vaStatus = vaEndPicture(mVADisplay, mVAContext);
310    mDecodingFrame = false;
311    CHECK_VA_STATUS("vaRenderPicture");
312
313    return DECODE_SUCCESS;
314}
315
316
317Decode_Status VideoDecoderWMV::setReference(
318        VAPictureParameterBufferVC1 *params,
319        int32_t picIndex,
320        VASurfaceID current) {
321    int frameType = params->picture_fields.bits.picture_type;
322    switch (frameType) {
323        case VC1_PTYPE_I:
324            params->forward_reference_picture = current;
325            params->backward_reference_picture = current;
326            break;
327        case VC1_PTYPE_P:
328            // check REFDIST in the picture parameter buffer
329            if (0 != params->reference_fields.bits.reference_distance_flag &&
330                0 != params->reference_fields.bits.reference_distance) {
331                /* The previous decoded frame (distance is up to 16 but not 0) is used
332                            for reference. Not supported here.
333                            */
334                return DECODE_NO_REFERENCE;
335            }
336            if (1 == picIndex) {
337                // handle interlace field coding case
338                if (1 == params->reference_fields.bits.num_reference_pictures ||
339                    1 == params->reference_fields.bits.reference_field_pic_indicator) {
340                    /*
341                                    two reference fields or the second closest I/P field is used for
342                                    prediction. Set forward reference picture to INVALID so it will be
343                                    updated to a valid previous reconstructed reference frame later.
344                                    */
345                    params->forward_reference_picture = VA_INVALID_SURFACE;
346                } else {
347                   /* the closest I/P is used for reference so it must be the
348                                  complementary field in the same surface.
349                                 */
350                    params->forward_reference_picture = current;
351                }
352            }
353            if (VA_INVALID_SURFACE == params->forward_reference_picture) {
354                if (mLastReference == NULL) {
355                    return DECODE_NO_REFERENCE;
356                }
357                params->forward_reference_picture = mLastReference->renderBuffer.surface;
358            }
359            params->backward_reference_picture = VA_INVALID_SURFACE;
360            break;
361        case VC1_PTYPE_B:
362            if (mForwardReference == NULL || mLastReference == NULL) {
363                return DECODE_NO_REFERENCE;
364            }
365            params->forward_reference_picture = mForwardReference->renderBuffer.surface;
366            params->backward_reference_picture = mLastReference->renderBuffer.surface;
367            break;
368        case VC1_PTYPE_BI:
369            params->forward_reference_picture = VA_INVALID_SURFACE;
370            params->backward_reference_picture = VA_INVALID_SURFACE;
371            break;
372        case VC1_PTYPE_SKIPPED:
373            //Will never happen here
374            break;
375        default:
376            break;
377    }
378    return DECODE_SUCCESS;
379}
380
381void VideoDecoderWMV::updateDeblockedPicIndexes(int frameType) {
382    int32_t curPicIndex = mDeblockedCurrPicIndex;
383
384    /* Out Loop (range map) buffers */
385    if (frameType != VC1_PTYPE_SKIPPED) {
386        if ((frameType == VC1_PTYPE_I) || (frameType == VC1_PTYPE_P)) {
387            mDeblockedCurrPicIndex = mDeblockedLastPicIndex;
388            mDeblockedLastPicIndex = curPicIndex;
389        } else {
390            mDeblockedCurrPicIndex = mDeblockedForwardPicIndex;
391            mDeblockedForwardPicIndex = curPicIndex;
392        }
393    }
394}
395
396Decode_Status VideoDecoderWMV::updateConfigData(
397        uint8_t *configData,
398        int32_t configDataLen,
399        uint8_t **newConfigData,
400        int32_t* newConfigDataLen) {
401    int32_t i = 0;
402    uint8_t *p = configData;
403
404    /* Check for start codes.  If one exist, then this is VC-1 and not WMV. */
405    while (i < configDataLen - 2) {
406        if ((p[i] == 0) &&
407            (p[i + 1] == 0) &&
408            (p[i + 2] == 1)) {
409            *newConfigData = NULL;
410            *newConfigDataLen = 0;
411            return DECODE_SUCCESS;
412        }
413        i++;
414    }
415
416    *newConfigDataLen = configDataLen + 9;
417    p = *newConfigData = new uint8_t [*newConfigDataLen];
418    if (!p) {
419       return DECODE_MEMORY_FAIL;
420    }
421
422    /* If we get here we have 4+ bytes of codec data that must be formatted */
423    /* to pass through as an RCV sequence header. */
424    p[0] = 0;
425    p[1] = 0;
426    p[2] = 1;
427    p[3] = 0x0f;  /* Start code. */
428    p[4] = (mVideoFormatInfo.width >> 8) & 0x0ff;
429    p[5] = mVideoFormatInfo.width & 0x0ff;
430    p[6] = (mVideoFormatInfo.height >> 8) & 0x0ff;
431    p[7] = mVideoFormatInfo.height & 0x0ff;
432
433    memcpy(p + 8, configData, configDataLen);
434    *(p + configDataLen + 8) = 0x80;
435
436    return DECODE_SUCCESS;
437}
438
439Decode_Status VideoDecoderWMV::startVA(vbp_data_vc1 *data) {
440    updateFormatInfo(data);
441
442    VAProfile vaProfile;
443    switch (data->se_data->PROFILE) {
444        case 0:
445        vaProfile = VAProfileVC1Simple;
446        break;
447        case 1:
448        vaProfile = VAProfileVC1Main;
449        break;
450        default:
451        vaProfile = VAProfileVC1Advanced;
452        break;
453    }
454
455    return VideoDecoderBase::setupVA(VC1_SURFACE_NUMBER, vaProfile, VC1_EXTRA_SURFACE_NUMBER);
456}
457
458void VideoDecoderWMV::updateFormatInfo(vbp_data_vc1 *data) {
459    ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d",
460        mVideoFormatInfo.width, mVideoFormatInfo.height,
461        data->se_data->CODED_WIDTH, data->se_data->CODED_HEIGHT);
462
463    mVideoFormatInfo.cropBottom = data->se_data->CODED_HEIGHT > mVideoFormatInfo.height ?
464                                                                           data->se_data->CODED_HEIGHT - mVideoFormatInfo.height : 0;
465    mVideoFormatInfo.cropRight = data->se_data->CODED_WIDTH > mVideoFormatInfo.width ?
466                                                                      data->se_data->CODED_WIDTH - mVideoFormatInfo.width : 0;
467
468     if ((mVideoFormatInfo.width != data->se_data->CODED_WIDTH ||
469        mVideoFormatInfo.height != data->se_data->CODED_HEIGHT) &&
470        data->se_data->CODED_WIDTH &&
471        data->se_data->CODED_HEIGHT) {
472        // encoded image size
473        mVideoFormatInfo.width = data->se_data->CODED_WIDTH;
474        mVideoFormatInfo.height = data->se_data->CODED_HEIGHT;
475        mSizeChanged = true;
476        ITRACE("Video size is changed.");
477    }
478
479    // scaling has been performed on the decoded image.
480    mVideoFormatInfo.videoRange = 1;
481
482    switch (data->se_data->MATRIX_COEF) {
483        case 1:
484            mVideoFormatInfo.colorMatrix = VA_SRC_BT709;
485            break;
486        // ITU-R BT.1700, ITU-R BT.601-5, and SMPTE 293M-1996.
487        case 6:
488            mVideoFormatInfo.colorMatrix = VA_SRC_BT601;
489            break;
490        default:
491            // unknown color matrix, set to 0 so color space flag will not be set.
492            mVideoFormatInfo.colorMatrix = 0;
493            break;
494    }
495
496    mVideoFormatInfo.aspectX = data->se_data->ASPECT_HORIZ_SIZE;
497    mVideoFormatInfo.aspectY = data->se_data->ASPECT_VERT_SIZE;
498    mVideoFormatInfo.bitrate = 0; //data->se_data->bitrate;
499    mVideoFormatInfo.valid = true;
500
501    setRenderRect();
502}
503
504Decode_Status VideoDecoderWMV::allocateVABufferIDs(int32_t number) {
505    if (mNumBufferIDs > number) {
506        return DECODE_SUCCESS;
507    }
508    if (mBufferIDs) {
509        delete [] mBufferIDs;
510    }
511    mBufferIDs = NULL;
512    mNumBufferIDs = 0;
513    mBufferIDs = new VABufferID [number];
514    if (mBufferIDs == NULL) {
515        return DECODE_MEMORY_FAIL;
516    }
517    mNumBufferIDs = number;
518    return DECODE_SUCCESS;
519}
520
521Decode_Status VideoDecoderWMV::parseBuffer(uint8_t *data, int32_t size, vbp_data_vc1 **vbpData) {
522    Decode_Status status;
523
524    if (data == NULL || size == 0) {
525        return DECODE_INVALID_DATA;
526    }
527
528    if (mConfigDataParsed) {
529        status = VideoDecoderBase::parseBuffer(data, size, false, (void**)vbpData);
530        CHECK_STATUS("VideoDecoderBase::parseBuffer");
531    } else {
532        uint8_t *newData = NULL;
533        int32_t newSize = 0;
534        status = updateConfigData(data, size, &newData, &newSize);
535        CHECK_STATUS("updateConfigData");
536
537        if (newSize) {
538            status = VideoDecoderBase::parseBuffer(newData, newSize, true, (void**)vbpData);
539            delete [] newData;
540        } else {
541            status = VideoDecoderBase::parseBuffer(data, size, true, (void**)vbpData);
542        }
543        CHECK_STATUS("VideoDecoderBase::parseBuffer");
544        mConfigDataParsed = true;
545    }
546    return DECODE_SUCCESS;
547}
548
549
550Decode_Status VideoDecoderWMV::checkHardwareCapability() {
551#ifndef USE_GEN_HW
552    VAStatus vaStatus;
553    VAConfigAttrib cfgAttribs[2];
554    cfgAttribs[0].type = VAConfigAttribMaxPictureWidth;
555    cfgAttribs[1].type = VAConfigAttribMaxPictureHeight;
556    vaStatus = vaGetConfigAttributes(mVADisplay, VAProfileVC1Advanced,
557            VAEntrypointVLD, cfgAttribs, 2);
558    CHECK_VA_STATUS("vaGetConfigAttributes");
559    if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) {
560        ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d",
561                cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height);
562        return DECODE_DRIVER_FAIL;
563    }
564#endif
565    return DECODE_SUCCESS;
566}
567
568
569