• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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