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
VideoDecoderWMV(const char * mimeType)21 VideoDecoderWMV::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
~VideoDecoderWMV()33 VideoDecoderWMV::~VideoDecoderWMV() {
34 stop();
35 }
36
start(VideoConfigBuffer * buffer)37 Decode_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
stop(void)56 void 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
flush(void)72 void VideoDecoderWMV::flush(void) {
73 VideoDecoderBase::flush();
74
75 mRangeMapped = false;
76 mDeblockedCurrPicIndex = 0;
77 mDeblockedLastPicIndex = 1;
78 mDeblockedForwardPicIndex = 2;
79 }
80
decode(VideoDecodeBuffer * buffer)81 Decode_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
decodeFrame(VideoDecodeBuffer * buffer,vbp_data_vc1 * data)151 Decode_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
decodePicture(vbp_data_vc1 * data,int32_t picIndex)238 Decode_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
setReference(VAPictureParameterBufferVC1 * params,int32_t picIndex,VASurfaceID current)336 Decode_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
updateDeblockedPicIndexes(int frameType)400 void 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
updateConfigData(uint8_t * configData,int32_t configDataLen,uint8_t ** newConfigData,int32_t * newConfigDataLen)415 Decode_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
startVA(vbp_data_vc1 * data)458 Decode_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
updateFormatInfo(vbp_data_vc1 * data)477 void 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
allocateVABufferIDs(int32_t number)524 Decode_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
parseBuffer(uint8_t * data,int32_t size,vbp_data_vc1 ** vbpData)541 Decode_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
checkHardwareCapability()570 Decode_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