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