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
VideoDecoderMPEG2(const char * mimeType)21 VideoDecoderMPEG2::VideoDecoderMPEG2(const char *mimeType)
22 : VideoDecoderBase(mimeType, VBP_MPEG2),
23 mBufferIDs(NULL),
24 mNumBufferIDs(0) {
25 //do nothing
26 }
27
~VideoDecoderMPEG2()28 VideoDecoderMPEG2::~VideoDecoderMPEG2() {
29 stop();
30 }
31
start(VideoConfigBuffer * buffer)32 Decode_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
stop(void)55 void VideoDecoderMPEG2::stop(void) {
56 if (mBufferIDs) {
57 delete [] mBufferIDs;
58 mBufferIDs = NULL;
59 }
60 mNumBufferIDs = 0;
61
62 VideoDecoderBase::stop();
63 }
64
decode(VideoDecodeBuffer * buffer)65 Decode_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
flush(void)152 void VideoDecoderMPEG2::flush(void) {
153 VideoDecoderBase::flush();
154 }
155
decodeFrame(VideoDecodeBuffer * buffer,vbp_data_mpeg2 * data)156 Decode_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
decodePicture(vbp_data_mpeg2 * data,int picIndex)206 Decode_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
setReference(VAPictureParameterBufferMPEG2 * picParam)290 Decode_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
startVA(vbp_data_mpeg2 * data)320 Decode_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
allocateVABufferIDs(int32_t number)343 Decode_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
updateFormatInfo(vbp_data_mpeg2 * data)360 void 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
checkHardwareCapability()410 Decode_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