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