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