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 "VideoDecoderMPEG2.h"
18#include "VideoDecoderTrace.h"
19#include <string.h>
20
21VideoDecoderMPEG2::VideoDecoderMPEG2(const char *mimeType)
22    : VideoDecoderBase(mimeType, VBP_MPEG2),
23    mBufferIDs(NULL),
24    mNumBufferIDs(0) {
25    //do nothing
26}
27
28VideoDecoderMPEG2::~VideoDecoderMPEG2() {
29    stop();
30}
31
32Decode_Status VideoDecoderMPEG2::start(VideoConfigBuffer *buffer) {
33    Decode_Status status;
34
35    status = VideoDecoderBase::start(buffer);
36    CHECK_STATUS("VideoDecoderBase::start");
37
38    if (buffer->data == NULL || buffer->size == 0) {
39        WTRACE("No config data to start VA.");
40        return DECODE_SUCCESS;
41    }
42
43    vbp_data_mpeg2 *data = NULL;
44    status = VideoDecoderBase::parseBuffer(
45            buffer->data,
46            buffer->size,
47            true, // config flag
48            (void**)&data);
49    CHECK_STATUS("VideoDecoderBase::parseBuffer");
50
51    status = startVA(data);
52    return status;
53}
54
55void VideoDecoderMPEG2::stop(void) {
56    if (mBufferIDs) {
57        delete [] mBufferIDs;
58        mBufferIDs = NULL;
59    }
60    mNumBufferIDs = 0;
61
62    VideoDecoderBase::stop();
63}
64
65Decode_Status VideoDecoderMPEG2::decode(VideoDecodeBuffer *buffer) {
66    Decode_Status status;
67    vbp_data_mpeg2 *data = NULL;
68    bool useGraphicbuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
69
70    if (buffer == NULL) {
71        return DECODE_INVALID_DATA;
72    }
73
74#ifdef DUMP_INPUT_BUFFER
75    if (mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER) {
76        DumpInputBuffer(buffer, "mpeg2");
77    }
78#endif
79
80    buffer->ext = NULL;
81    status =  VideoDecoderBase::parseBuffer(
82            buffer->data,
83            buffer->size,
84            false,        // config flag
85            (void**)&data);
86    CHECK_STATUS("VideoDecoderBase::parseBuffer");
87
88    if (!mVAStarted) {
89        status = startVA(data);
90        CHECK_STATUS("startVA");
91    }
92
93    if (mSizeChanged && !useGraphicbuffer) {
94        // some container has the incorrect width/height.
95        // send the format change to OMX to update the crop info.
96        mSizeChanged = false;
97        ITRACE("Video size is changed during startVA");
98        return DECODE_FORMAT_CHANGE;
99    }
100
101    if ((mVideoFormatInfo.width != (uint32_t)data->codec_data->frame_width ||
102        mVideoFormatInfo.height != (uint32_t)data->codec_data->frame_height) &&
103        (data->codec_data->frame_width > 0) && (data->codec_data->frame_height)) {
104        // update  encoded image size
105        ITRACE("Video size is changed. from %dx%d to %dx%d\n",mVideoFormatInfo.width,mVideoFormatInfo.height, data->codec_data->frame_width,data->codec_data->frame_height);
106        if (useGraphicbuffer && mStoreMetaData) {
107            pthread_mutex_lock(&mFormatLock);
108        }
109        mVideoFormatInfo.width = data->codec_data->frame_width;
110        mVideoFormatInfo.height = data->codec_data->frame_height;
111        bool needFlush = false;
112        if (useGraphicbuffer) {
113            if (mStoreMetaData) {
114                needFlush = true;
115
116                mVideoFormatInfo.valid = false;
117                pthread_mutex_unlock(&mFormatLock);
118            } else {
119                needFlush = (mVideoFormatInfo.width > mVideoFormatInfo.surfaceWidth)
120                         || (mVideoFormatInfo.height > mVideoFormatInfo.surfaceHeight);
121            }
122        }
123
124        if (needFlush) {
125            if (mStoreMetaData) {
126                status = endDecodingFrame(false);
127                CHECK_STATUS("endDecodingFrame");
128            } else {
129                flushSurfaceBuffers();
130            }
131            mSizeChanged = false;
132            return DECODE_FORMAT_CHANGE;
133        } else {
134            mSizeChanged = true;
135        }
136
137        setRenderRect();
138    } else {
139        if (useGraphicbuffer && mStoreMetaData) {
140            mVideoFormatInfo.valid = true;
141        }
142    }
143
144    VideoDecoderBase::setRotationDegrees(buffer->rotationDegrees);
145
146    status = decodeFrame(buffer, data);
147    CHECK_STATUS("decodeFrame");
148
149    return status;
150}
151
152void VideoDecoderMPEG2::flush(void) {
153    VideoDecoderBase::flush();
154}
155
156Decode_Status VideoDecoderMPEG2::decodeFrame(VideoDecodeBuffer *buffer, vbp_data_mpeg2 *data) {
157    Decode_Status status;
158    // check if any slice is parsed, we may just receive configuration data
159    if (data->num_pictures == 0 || data->pic_data == NULL) {
160        WTRACE("Number of pictures is 0, buffer contains configuration data only?");
161        return DECODE_SUCCESS;
162    }
163
164    status = acquireSurfaceBuffer();
165    CHECK_STATUS("acquireSurfaceBuffer");
166
167    // set referenceFrame to true if frame decoded is I/P frame, false otherwise.
168    int frameType = data->codec_data->frame_type;
169    mAcquiredBuffer->referenceFrame = (frameType == MPEG2_PICTURE_TYPE_I || frameType == MPEG2_PICTURE_TYPE_P);
170
171    if (data->num_pictures > 1) {
172        if (data->pic_data[0].pic_parms->picture_coding_extension.bits.picture_structure == MPEG2_PIC_STRUCT_TOP)
173        {
174            mAcquiredBuffer->renderBuffer.scanFormat = VA_TOP_FIELD;
175        } else {
176            mAcquiredBuffer->renderBuffer.scanFormat = VA_BOTTOM_FIELD;
177        }
178    } else {
179        mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
180    }
181
182    mAcquiredBuffer->renderBuffer.timeStamp = buffer->timeStamp;
183    mAcquiredBuffer->renderBuffer.flag = 0;
184    if (buffer->flag & WANT_DECODE_ONLY) {
185        mAcquiredBuffer->renderBuffer.flag |= WANT_DECODE_ONLY;
186    }
187    if (mSizeChanged) {
188        mSizeChanged = false;
189        mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE;
190    }
191
192    for (uint32_t index = 0; index < data->num_pictures; index++) {
193        status = decodePicture(data, index);
194        if (status != DECODE_SUCCESS) {
195            endDecodingFrame(true);
196            return status;
197        }
198    }
199
200    // if sample is successfully decoded, call outputSurfaceBuffer(); otherwise
201    // call releaseSurfacebuffer();
202    status = outputSurfaceBuffer();
203    return status;
204}
205
206Decode_Status VideoDecoderMPEG2::decodePicture(vbp_data_mpeg2 *data, int picIndex) {
207    Decode_Status status;
208    VAStatus vaStatus;
209    uint32_t bufferIDCount = 0;
210
211    vbp_picture_data_mpeg2 *picData = &(data->pic_data[picIndex]);
212    VAPictureParameterBufferMPEG2 *picParam = picData->pic_parms;
213
214    status = allocateVABufferIDs(picData->num_slices * 2 + 2);
215    CHECK_STATUS("allocateVABufferIDs")
216
217    // send picture parametre for each slice
218    status = setReference(picParam);
219    CHECK_STATUS("setReference");
220
221    vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
222    CHECK_VA_STATUS("vaBeginPicture");
223    // setting mDecodingFrame to true so vaEndPicture will be invoked to end the picture decoding.
224    mDecodingFrame = true;
225
226    vaStatus = vaCreateBuffer(
227            mVADisplay,
228            mVAContext,
229            VAPictureParameterBufferType,
230            sizeof(VAPictureParameterBufferMPEG2),
231            1,
232            picParam,
233            &mBufferIDs[bufferIDCount]);
234    CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
235    bufferIDCount++;
236
237    vaStatus = vaCreateBuffer(
238                mVADisplay,
239                mVAContext,
240                VAIQMatrixBufferType,
241                sizeof(VAIQMatrixBufferMPEG2),
242                1,
243                data->iq_matrix_buffer,
244                &mBufferIDs[bufferIDCount]);
245    CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
246    bufferIDCount++;
247
248    for (uint32_t i = 0; i < picData->num_slices; i++) {
249        vaStatus = vaCreateBuffer(
250                mVADisplay,
251                mVAContext,
252                VASliceParameterBufferType,
253                sizeof(VASliceParameterBufferMPEG2),
254                1,
255                &(picData->slice_data[i].slice_param),
256                &mBufferIDs[bufferIDCount]);
257        CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
258        bufferIDCount++;
259
260        // slice data buffer pointer
261        // Note that this is the original data buffer ptr;
262        // offset to the actual slice data is provided in
263        // slice_data_offset in VASliceParameterBufferMPEG2
264        vaStatus = vaCreateBuffer(
265                mVADisplay,
266                mVAContext,
267                VASliceDataBufferType,
268                picData->slice_data[i].slice_size, //size
269                1,        //num_elements
270                picData->slice_data[i].buffer_addr + picData->slice_data[i].slice_offset,
271                &mBufferIDs[bufferIDCount]);
272        CHECK_VA_STATUS("vaCreateSliceDataBuffer");
273        bufferIDCount++;
274    }
275
276    vaStatus = vaRenderPicture(
277            mVADisplay,
278            mVAContext,
279            mBufferIDs,
280            bufferIDCount);
281    CHECK_VA_STATUS("vaRenderPicture");
282
283    vaStatus = vaEndPicture(mVADisplay, mVAContext);
284    mDecodingFrame = false;
285    CHECK_VA_STATUS("vaRenderPicture");
286
287    return DECODE_SUCCESS;
288}
289
290Decode_Status VideoDecoderMPEG2::setReference(VAPictureParameterBufferMPEG2 *picParam) {
291    switch (picParam->picture_coding_type) {
292        case MPEG2_PICTURE_TYPE_I:
293            picParam->forward_reference_picture = VA_INVALID_SURFACE;
294            picParam->backward_reference_picture = VA_INVALID_SURFACE;
295            break;
296        case MPEG2_PICTURE_TYPE_P:
297            if (mLastReference != NULL) {
298                picParam->forward_reference_picture = mLastReference->renderBuffer.surface;
299            } else {
300                VTRACE("%s: no reference frame, but keep decoding", __FUNCTION__);
301                picParam->forward_reference_picture = VA_INVALID_SURFACE;
302            }
303            picParam->backward_reference_picture = VA_INVALID_SURFACE;
304            break;
305        case MPEG2_PICTURE_TYPE_B:
306            if (mLastReference == NULL || mForwardReference == NULL) {
307                return DECODE_NO_REFERENCE;
308            } else {
309                picParam->forward_reference_picture = mForwardReference->renderBuffer.surface;
310                picParam->backward_reference_picture = mLastReference->renderBuffer.surface;
311            }
312            break;
313        default:
314            // Will never reach here;
315            return DECODE_PARSER_FAIL;
316    }
317    return DECODE_SUCCESS;
318}
319
320Decode_Status VideoDecoderMPEG2::startVA(vbp_data_mpeg2 *data) {
321    updateFormatInfo(data);
322
323    VAProfile vaProfile;
324
325    // profile_and_level_indication is 8-bit field
326    // | x | x x x | x x x x|
327    //      profile  level
328    // profile: 101 - simple
329    //          100 - main
330    // level:   1010 - low
331    //          1000 - main
332    //          0100 - high
333    //          0110 - high 1440
334    if ((data->codec_data->profile_and_level_indication & 0x70) == 0x50) {
335        vaProfile = VAProfileMPEG2Simple;
336    } else {
337        vaProfile = VAProfileMPEG2Main;
338    }
339
340    return VideoDecoderBase::setupVA(MPEG2_SURFACE_NUMBER, vaProfile);
341}
342
343Decode_Status VideoDecoderMPEG2::allocateVABufferIDs(int32_t number) {
344    if (mNumBufferIDs > number) {
345        return DECODE_SUCCESS;
346    }
347    if (mBufferIDs) {
348        delete [] mBufferIDs;
349    }
350    mBufferIDs = NULL;
351    mNumBufferIDs = 0;
352    mBufferIDs = new VABufferID [number];
353    if (mBufferIDs == NULL) {
354        return DECODE_MEMORY_FAIL;
355    }
356    mNumBufferIDs = number;
357    return DECODE_SUCCESS;
358}
359
360void VideoDecoderMPEG2::updateFormatInfo(vbp_data_mpeg2 *data) {
361    ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d",
362        mVideoFormatInfo.width, mVideoFormatInfo.height,
363        data->codec_data->frame_width,
364        data->codec_data->frame_height);
365
366    mVideoFormatInfo.cropBottom = (data->codec_data->frame_height > mVideoFormatInfo.height) ?
367                                                       (data->codec_data->frame_height - mVideoFormatInfo.height) : 0;
368    mVideoFormatInfo.cropRight = (data->codec_data->frame_width > mVideoFormatInfo.width) ?
369                                                       (data->codec_data->frame_width - mVideoFormatInfo.width) : 0;
370
371    if ((mVideoFormatInfo.width != (uint32_t)data->codec_data->frame_width ||
372         mVideoFormatInfo.height != (uint32_t)data->codec_data->frame_height) &&
373        (data->codec_data->frame_width > 0) && (data->codec_data->frame_height)) {
374        // update  encoded image size
375        mVideoFormatInfo.width = data->codec_data->frame_width;
376        mVideoFormatInfo.height = data->codec_data->frame_height;
377        mSizeChanged = true;
378        ITRACE("Video size is changed.");
379    }
380
381    // video_range has default value of 0. Y ranges from 16 to 235.
382    mVideoFormatInfo.videoRange = data->codec_data->video_range;
383
384    switch (data->codec_data->matrix_coefficients) {
385        case 1:
386            mVideoFormatInfo.colorMatrix = VA_SRC_BT709;
387            break;
388
389        // ITU-R Recommendation BT.470-6 System B, G (MP4), same as
390        // SMPTE 170M/BT601
391        case 5:
392        case 6:
393            mVideoFormatInfo.colorMatrix = VA_SRC_BT601;
394            break;
395
396        default:
397            // unknown color matrix, set to 0 so color space flag will not be set.
398            mVideoFormatInfo.colorMatrix = 0;
399            break;
400    }
401
402    mVideoFormatInfo.aspectX = data->codec_data->par_width;
403    mVideoFormatInfo.aspectY = data->codec_data->par_height;
404    mVideoFormatInfo.bitrate = data->codec_data->bit_rate;
405    mVideoFormatInfo.valid = true;
406
407    setRenderRect();
408}
409
410Decode_Status VideoDecoderMPEG2::checkHardwareCapability() {
411    VAStatus vaStatus;
412    VAConfigAttrib cfgAttribs[2];
413    cfgAttribs[0].type = VAConfigAttribMaxPictureWidth;
414    cfgAttribs[1].type = VAConfigAttribMaxPictureHeight;
415    vaStatus = vaGetConfigAttributes(mVADisplay,
416            VAProfileMPEG2Main,
417            VAEntrypointVLD, cfgAttribs, 2);
418    CHECK_VA_STATUS("vaGetConfigAttributes");
419    if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) {
420        ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d",
421                cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height);
422        return DECODE_DRIVER_FAIL;
423    }
424    return DECODE_SUCCESS;
425}
426