• 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 "VideoDecoderBase.h"
18 #include "VideoDecoderTrace.h"
19 #include <string.h>
20 #include <va/va_android.h>
21 #include <va/va_tpi.h>
22 #ifdef  __SSE4_1__
23 #include "use_util_sse4.h"
24 #endif
25 
26 #define INVALID_PTS ((uint64_t)-1)
27 #define MAXIMUM_POC  0x7FFFFFFF
28 #define MINIMUM_POC  0x80000000
29 #define ANDROID_DISPLAY_HANDLE 0x18C34078
30 
VideoDecoderBase(const char * mimeType,_vbp_parser_type type)31 VideoDecoderBase::VideoDecoderBase(const char *mimeType, _vbp_parser_type type)
32     : mInitialized(false),
33       mLowDelay(false),
34       mDisplay(NULL),
35       mVADisplay(NULL),
36       mVAContext(VA_INVALID_ID),
37       mVAConfig(VA_INVALID_ID),
38       mVAStarted(false),
39       mCurrentPTS(INVALID_PTS),
40       mAcquiredBuffer(NULL),
41       mLastReference(NULL),
42       mForwardReference(NULL),
43       mDecodingFrame(false),
44       mSizeChanged(false),
45       mShowFrame(true),
46       mOutputWindowSize(OUTPUT_WINDOW_SIZE),
47       mRotationDegrees(0),
48       mErrReportEnabled(false),
49       mWiDiOn(false),
50       mRawOutput(false),
51       mManageReference(true),
52       mOutputMethod(OUTPUT_BY_PCT),
53       mNumSurfaces(0),
54       mSurfaceBuffers(NULL),
55       mOutputHead(NULL),
56       mOutputTail(NULL),
57       mSurfaces(NULL),
58       mVASurfaceAttrib(NULL),
59       mSurfaceUserPtr(NULL),
60       mSurfaceAcquirePos(0),
61       mNextOutputPOC(MINIMUM_POC),
62       mParserType(type),
63       mParserHandle(NULL),
64       mSignalBufferSize(0) {
65 
66     memset(&mVideoFormatInfo, 0, sizeof(VideoFormatInfo));
67     memset(&mConfigBuffer, 0, sizeof(mConfigBuffer));
68     for (int i = 0; i < MAX_GRAPHIC_BUFFER_NUM; i++) {
69          mSignalBufferPre[i] = NULL;
70     }
71     pthread_mutex_init(&mLock, NULL);
72     mVideoFormatInfo.mimeType = strdup(mimeType);
73     mUseGEN = false;
74     mLibHandle = NULL;
75     mParserOpen = NULL;
76     mParserClose = NULL;
77     mParserParse = NULL;
78     mParserQuery = NULL;
79     mParserFlush = NULL;
80     mParserUpdate = NULL;
81 }
82 
~VideoDecoderBase()83 VideoDecoderBase::~VideoDecoderBase() {
84     pthread_mutex_destroy(&mLock);
85     stop();
86     free(mVideoFormatInfo.mimeType);
87 }
88 
start(VideoConfigBuffer * buffer)89 Decode_Status VideoDecoderBase::start(VideoConfigBuffer *buffer) {
90     if (buffer == NULL) {
91         return DECODE_INVALID_DATA;
92     }
93 
94     if (mParserHandle != NULL) {
95         WTRACE("Decoder has already started.");
96         return DECODE_SUCCESS;
97     }
98     mLibHandle = dlopen("libmixvbp.so", RTLD_NOW);
99     if (mLibHandle == NULL) {
100        return DECODE_NO_PARSER;
101     }
102     mParserOpen = (OpenFunc)dlsym(mLibHandle, "vbp_open");
103     mParserClose = (CloseFunc)dlsym(mLibHandle, "vbp_close");
104     mParserParse = (ParseFunc)dlsym(mLibHandle, "vbp_parse");
105     mParserQuery = (QueryFunc)dlsym(mLibHandle, "vbp_query");
106     mParserFlush = (FlushFunc)dlsym(mLibHandle, "vbp_flush");
107     if (mParserOpen == NULL || mParserClose == NULL || mParserParse == NULL
108         || mParserQuery == NULL || mParserFlush == NULL) {
109         return DECODE_NO_PARSER;
110     }
111 #if (defined USE_AVC_SHORT_FORMAT || defined USE_SLICE_HEADER_PARSING)
112     mParserUpdate = (UpdateFunc)dlsym(mLibHandle, "vbp_update");
113     if (mParserUpdate == NULL) {
114         return DECODE_NO_PARSER;
115     }
116 #endif
117     if ((int32_t)mParserType != VBP_INVALID) {
118         ITRACE("mParserType = %d", mParserType);
119         if (mParserOpen(mParserType, &mParserHandle) != VBP_OK) {
120             ETRACE("Failed to open VBP parser.");
121             return DECODE_NO_PARSER;
122         }
123     }
124     // keep a copy of configure buffer, meta data only. It can be used to override VA setup parameter.
125     mConfigBuffer = *buffer;
126     mConfigBuffer.data = NULL;
127     mConfigBuffer.size = 0;
128 
129     mVideoFormatInfo.width = buffer->width;
130     mVideoFormatInfo.height = buffer->height;
131     if (buffer->flag & USE_NATIVE_GRAPHIC_BUFFER) {
132         mVideoFormatInfo.surfaceWidth = buffer->graphicBufferWidth;
133         mVideoFormatInfo.surfaceHeight = buffer->graphicBufferHeight;
134     }
135     mLowDelay = buffer->flag & WANT_LOW_DELAY;
136     mRawOutput = buffer->flag & WANT_RAW_OUTPUT;
137     if (mRawOutput) {
138         WTRACE("Output is raw data.");
139     }
140 
141     return DECODE_SUCCESS;
142 }
143 
144 
reset(VideoConfigBuffer * buffer)145 Decode_Status VideoDecoderBase::reset(VideoConfigBuffer *buffer) {
146     if (buffer == NULL) {
147         return DECODE_INVALID_DATA;
148     }
149 
150     // if VA is already started, terminate VA as graphic buffers are reallocated by omxcodec
151     terminateVA();
152 
153     // reset the mconfigBuffer to pass it for startVA.
154     mConfigBuffer = *buffer;
155     mConfigBuffer.data = NULL;
156     mConfigBuffer.size = 0;
157 
158     mVideoFormatInfo.width = buffer->width;
159     mVideoFormatInfo.height = buffer->height;
160     if (buffer->flag & USE_NATIVE_GRAPHIC_BUFFER) {
161         mVideoFormatInfo.surfaceWidth = buffer->graphicBufferWidth;
162         mVideoFormatInfo.surfaceHeight = buffer->graphicBufferHeight;
163     }
164     mVideoFormatInfo.actualBufferNeeded = mConfigBuffer.surfaceNumber;
165     mLowDelay = buffer->flag & WANT_LOW_DELAY;
166     mRawOutput = buffer->flag & WANT_RAW_OUTPUT;
167     if (mRawOutput) {
168         WTRACE("Output is raw data.");
169     }
170     return DECODE_SUCCESS;
171 }
172 
173 
174 
stop(void)175 void VideoDecoderBase::stop(void) {
176     terminateVA();
177 
178     mCurrentPTS = INVALID_PTS;
179     mAcquiredBuffer = NULL;
180     mLastReference = NULL;
181     mForwardReference = NULL;
182     mDecodingFrame = false;
183     mSizeChanged = false;
184 
185     // private variables
186     mLowDelay = false;
187     mRawOutput = false;
188     mNumSurfaces = 0;
189     mSurfaceAcquirePos = 0;
190     mNextOutputPOC = MINIMUM_POC;
191     mVideoFormatInfo.valid = false;
192     if (mParserHandle){
193         mParserClose(mParserHandle);
194         mParserHandle = NULL;
195     }
196     if (mLibHandle) {
197         dlclose(mLibHandle);
198         mLibHandle = NULL;
199     }
200 }
201 
flush(void)202 void VideoDecoderBase::flush(void) {
203     if (mVAStarted == false) {
204         // nothing to flush at this stage
205         return;
206     }
207 
208     endDecodingFrame(true);
209 
210     VideoSurfaceBuffer *p = mOutputHead;
211     // check if there's buffer with DRC flag in the output queue
212     while (p) {
213         if (p->renderBuffer.flag & IS_RESOLUTION_CHANGE) {
214             mSizeChanged = true;
215             break;
216         }
217         p = p->next;
218     }
219     // avoid setting mSurfaceAcquirePos  to 0 as it may cause tearing
220     // (surface is still being rendered)
221     mSurfaceAcquirePos = (mSurfaceAcquirePos  + 1) % mNumSurfaces;
222     mNextOutputPOC = MINIMUM_POC;
223     mCurrentPTS = INVALID_PTS;
224     mAcquiredBuffer = NULL;
225     mLastReference = NULL;
226     mForwardReference = NULL;
227     mOutputHead = NULL;
228     mOutputTail = NULL;
229     mDecodingFrame = false;
230 
231     // flush vbp parser
232     if (mParserHandle && (mParserFlush(mParserHandle) != VBP_OK)) {
233         WTRACE("Failed to flush parser. Continue");
234     }
235 
236     // initialize surface buffer without resetting mapped/raw data
237     initSurfaceBuffer(false);
238 
239 }
240 
freeSurfaceBuffers(void)241 void VideoDecoderBase::freeSurfaceBuffers(void) {
242     if (mVAStarted == false) {
243         // nothing to free surface buffers at this stage
244         return;
245     }
246 
247     pthread_mutex_lock(&mLock);
248 
249     endDecodingFrame(true);
250 
251     // if VA is already started, terminate VA as graphic buffers are reallocated by omxcodec
252     terminateVA();
253 
254     pthread_mutex_unlock(&mLock);
255 }
256 
getFormatInfo(void)257 const VideoFormatInfo* VideoDecoderBase::getFormatInfo(void) {
258     return &mVideoFormatInfo;
259 }
260 
getOutput(bool draining,VideoErrorBuffer * outErrBuf)261 const VideoRenderBuffer* VideoDecoderBase::getOutput(bool draining, VideoErrorBuffer *outErrBuf) {
262     VAStatus vaStatus;
263     if (mVAStarted == false) {
264         return NULL;
265     }
266     bool useGraphicBuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
267 
268     if (draining) {
269         // complete decoding the last frame and ignore return
270         endDecodingFrame(false);
271     }
272 
273     if (mOutputHead == NULL) {
274         return NULL;
275     }
276 
277     // output by position (the first buffer)
278     VideoSurfaceBuffer *outputByPos = mOutputHead;
279 
280     if (mLowDelay) {
281         mOutputHead = mOutputHead->next;
282         if (mOutputHead == NULL) {
283             mOutputTail = NULL;
284         }
285         vaStatus = vaSetTimestampForSurface(mVADisplay, outputByPos->renderBuffer.surface, outputByPos->renderBuffer.timeStamp);
286         if (useGraphicBuffer && !mUseGEN) {
287             vaSyncSurface(mVADisplay, outputByPos->renderBuffer.surface);
288             fillDecodingErrors(&(outputByPos->renderBuffer));
289         }
290         if (draining && mOutputTail == NULL) {
291             outputByPos->renderBuffer.flag |= IS_EOS;
292         }
293         drainDecodingErrors(outErrBuf, &(outputByPos->renderBuffer));
294 
295         return &(outputByPos->renderBuffer);
296     }
297 
298     // output by presentation time stamp (the smallest pts)
299     VideoSurfaceBuffer *outputByPts = findOutputByPts();
300 
301     VideoSurfaceBuffer *output = NULL;
302     if (mOutputMethod == OUTPUT_BY_POC) {
303         output = findOutputByPoc(draining);
304     } else if (mOutputMethod == OUTPUT_BY_PCT) {
305         output = findOutputByPct(draining);
306     } else {
307         ETRACE("Invalid output method.");
308         return NULL;
309     }
310 
311     if (output == NULL) {
312         return NULL;
313     }
314 
315     if (output != outputByPts) {
316         // swap time stamp
317         uint64_t ts = output->renderBuffer.timeStamp;
318         output->renderBuffer.timeStamp = outputByPts->renderBuffer.timeStamp;
319         outputByPts->renderBuffer.timeStamp = ts;
320     }
321 
322     if (output != outputByPos) {
323         // remove this output from middle or end of the list
324         VideoSurfaceBuffer *p = outputByPos;
325         while (p->next != output) {
326             p = p->next;
327         }
328         p->next = output->next;
329         if (mOutputTail == output) {
330             mOutputTail = p;
331         }
332     } else {
333         // remove this output from head of the list
334         mOutputHead = mOutputHead->next;
335         if (mOutputHead == NULL) {
336             mOutputTail = NULL;
337         }
338     }
339     //VTRACE("Output POC %d for display (pts = %.2f)", output->pictureOrder, output->renderBuffer.timeStamp/1E6);
340     vaStatus = vaSetTimestampForSurface(mVADisplay, output->renderBuffer.surface, output->renderBuffer.timeStamp);
341 
342     if (useGraphicBuffer && !mUseGEN) {
343         vaSyncSurface(mVADisplay, output->renderBuffer.surface);
344         fillDecodingErrors(&(output->renderBuffer));
345     }
346 
347     if (draining && mOutputTail == NULL) {
348         output->renderBuffer.flag |= IS_EOS;
349     }
350 
351     drainDecodingErrors(outErrBuf, &(output->renderBuffer));
352 
353     return &(output->renderBuffer);
354 }
355 
findOutputByPts()356 VideoSurfaceBuffer* VideoDecoderBase::findOutputByPts() {
357     // output by presentation time stamp - buffer with the smallest time stamp is output
358     VideoSurfaceBuffer *p = mOutputHead;
359     VideoSurfaceBuffer *outputByPts = NULL;
360     uint64_t pts = INVALID_PTS;
361     do {
362         if ((uint64_t)(p->renderBuffer.timeStamp) <= pts) {
363             // find buffer with the smallest PTS
364             pts = p->renderBuffer.timeStamp;
365             outputByPts = p;
366         }
367         p = p->next;
368     } while (p != NULL);
369 
370     return outputByPts;
371 }
372 
findOutputByPct(bool draining)373 VideoSurfaceBuffer* VideoDecoderBase::findOutputByPct(bool draining) {
374     // output by picture coding type (PCT)
375     // if there is more than one reference frame, the first reference frame is ouput, otherwise,
376     // output non-reference frame if there is any.
377 
378     VideoSurfaceBuffer *p = mOutputHead;
379     VideoSurfaceBuffer *outputByPct = NULL;
380     int32_t reference = 0;
381     do {
382         if (p->referenceFrame) {
383             reference++;
384             if (reference > 1) {
385                 // mOutputHead must be a reference frame
386                 outputByPct = mOutputHead;
387                 break;
388             }
389         } else {
390             // first non-reference frame
391             outputByPct = p;
392             break;
393         }
394         p = p->next;
395     } while (p != NULL);
396 
397     if (outputByPct == NULL && draining) {
398         outputByPct = mOutputHead;
399     }
400     return  outputByPct;
401 }
402 
403 #if 0
404 VideoSurfaceBuffer* VideoDecoderBase::findOutputByPoc(bool draining) {
405     // output by picture order count (POC)
406     // Output criteria:
407     // if there is IDR frame (POC == 0), all the frames before IDR must be output;
408     // Otherwise, if draining flag is set or list is full, frame with the least POC is output;
409     // Otherwise, NOTHING is output
410 
411     int32_t dpbFullness = 0;
412     for (int32_t i = 0; i < mNumSurfaces; i++) {
413         // count num of reference frames
414         if (mSurfaceBuffers[i].asReferernce) {
415             dpbFullness++;
416         }
417     }
418 
419     if (mAcquiredBuffer && mAcquiredBuffer->asReferernce) {
420         // frame is being decoded and is not ready for output yet
421         dpbFullness--;
422     }
423 
424     VideoSurfaceBuffer *p = mOutputHead;
425     while (p != NULL) {
426         // count dpbFullness with non-reference frame in the output queue
427         if (p->asReferernce == false) {
428             dpbFullness++;
429         }
430         p = p->next;
431     }
432 
433 Retry:
434     p = mOutputHead;
435     VideoSurfaceBuffer *outputByPoc = NULL;
436     int32_t count = 0;
437     int32_t poc = MAXIMUM_POC;
438 
439     do {
440         if (p->pictureOrder == 0) {
441             // output picture with the least POC before IDR
442             if (outputByPoc != NULL) {
443                 mNextOutputPOC = outputByPoc->pictureOrder + 1;
444                 return outputByPoc;
445             } else {
446                 mNextOutputPOC = MINIMUM_POC;
447             }
448         }
449 
450         // POC of  the output candidate must not be less than mNextOutputPOC
451         if (p->pictureOrder < mNextOutputPOC) {
452             break;
453         }
454 
455         if (p->pictureOrder < poc) {
456             // update the least POC.
457             poc = p->pictureOrder;
458             outputByPoc = p;
459         }
460         count++;
461         p = p->next;
462     } while (p != NULL && count < mOutputWindowSize);
463 
464     if (draining == false && dpbFullness < mOutputWindowSize) {
465         // list is not  full and we are not  in draining state
466         // if DPB is already full, one frame must be output
467         return NULL;
468     }
469 
470     if (outputByPoc == NULL) {
471         mNextOutputPOC = MINIMUM_POC;
472         goto Retry;
473     }
474 
475     // for debugging purpose
476     if (outputByPoc->pictureOrder != 0 && outputByPoc->pictureOrder < mNextOutputPOC) {
477         ETRACE("Output POC is not incremental, expected %d, actual %d", mNextOutputPOC, outputByPoc->pictureOrder);
478         //gaps_in_frame_num_value_allowed_flag is not currently supported
479     }
480 
481     mNextOutputPOC = outputByPoc->pictureOrder + 1;
482 
483     return outputByPoc;
484 }
485 #else
findOutputByPoc(bool draining)486 VideoSurfaceBuffer* VideoDecoderBase::findOutputByPoc(bool draining) {
487     VideoSurfaceBuffer *output = NULL;
488     VideoSurfaceBuffer *p = mOutputHead;
489     int32_t count = 0;
490     int32_t poc = MAXIMUM_POC;
491     VideoSurfaceBuffer *outputleastpoc = mOutputHead;
492     do {
493         count++;
494         if (p->pictureOrder == 0) {
495             // any picture before this POC (new IDR) must be output
496             if (output == NULL) {
497                 mNextOutputPOC = MINIMUM_POC;
498                 // looking for any POC with negative value
499             } else {
500                 mNextOutputPOC = output->pictureOrder + 1;
501                 break;
502             }
503         }
504         if (p->pictureOrder < poc && p->pictureOrder >= mNextOutputPOC) {
505             // this POC meets ouput criteria.
506             poc = p->pictureOrder;
507             output = p;
508             outputleastpoc = p;
509         }
510         if (poc == mNextOutputPOC || count == mOutputWindowSize) {
511             if (output != NULL) {
512                 // this indicates two cases:
513                 // 1) the next output POC is found.
514                 // 2) output queue is full and there is at least one buffer meeting the output criteria.
515                 mNextOutputPOC = output->pictureOrder + 1;
516                 break;
517             } else {
518                 // this indicates output queue is full and no buffer in the queue meets the output criteria
519                 // restart processing as queue is FULL and output criteria is changed. (next output POC is 0)
520                 mNextOutputPOC = MINIMUM_POC;
521                 count = 0;
522                 poc = MAXIMUM_POC;
523                 p = mOutputHead;
524                 continue;
525             }
526         }
527         if (p->next == NULL) {
528             output = NULL;
529         }
530 
531         p = p->next;
532     } while (p != NULL);
533 
534     if (draining == true && output == NULL) {
535         output = outputleastpoc;
536     }
537 
538     return output;
539 }
540 #endif
541 
checkBufferAvail(void)542 bool VideoDecoderBase::checkBufferAvail(void) {
543     if (!mInitialized) {
544         if ((mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER) == 0) {
545             return true;
546         }
547         for (int i = 0; i < MAX_GRAPHIC_BUFFER_NUM; i++) {
548             if (mSignalBufferPre[i] != NULL) {
549                 return true;
550             }
551         }
552         return false;
553     }
554     // check whether there is buffer available for decoding
555     // TODO: check frame being referenced for frame skipping
556     VideoSurfaceBuffer *buffer = NULL;
557     for (int32_t i = 0; i < mNumSurfaces; i++) {
558         buffer = mSurfaceBuffers + i;
559 
560         if (buffer->asReferernce == false &&
561             buffer->renderBuffer.renderDone == true) {
562             querySurfaceRenderStatus(buffer);
563             if (buffer->renderBuffer.driverRenderDone == true)
564                 return true;
565         }
566      }
567     return false;
568 }
569 
acquireSurfaceBuffer(void)570 Decode_Status VideoDecoderBase::acquireSurfaceBuffer(void) {
571     if (mVAStarted == false) {
572         return DECODE_FAIL;
573     }
574 
575     if (mAcquiredBuffer != NULL) {
576         ETRACE("mAcquiredBuffer is not NULL. Implementation bug.");
577         return DECODE_FAIL;
578     }
579 
580     int nextAcquire = mSurfaceAcquirePos;
581     VideoSurfaceBuffer *acquiredBuffer = NULL;
582     bool acquired = false;
583 
584     while (acquired == false) {
585         acquiredBuffer = mSurfaceBuffers + nextAcquire;
586 
587         querySurfaceRenderStatus(acquiredBuffer);
588 
589         if (acquiredBuffer->asReferernce == false && acquiredBuffer->renderBuffer.renderDone == true && acquiredBuffer->renderBuffer.driverRenderDone == true) {
590             // this is potential buffer for acquisition. Check if it is referenced by other surface for frame skipping
591             VideoSurfaceBuffer *temp;
592             acquired = true;
593             for (int i = 0; i < mNumSurfaces; i++) {
594                 if (i == nextAcquire) {
595                     continue;
596                 }
597                 temp = mSurfaceBuffers + i;
598                 // use mSurfaces[nextAcquire] instead of acquiredBuffer->renderBuffer.surface as its the actual surface to use.
599                 if (temp->renderBuffer.surface == mSurfaces[nextAcquire] &&
600                     temp->renderBuffer.renderDone == false) {
601                     ITRACE("Surface is referenced by other surface buffer.");
602                     acquired = false;
603                     break;
604                 }
605             }
606         }
607         if (acquired) {
608             break;
609         }
610         nextAcquire++;
611         if (nextAcquire == mNumSurfaces) {
612             nextAcquire = 0;
613         }
614         if (nextAcquire == mSurfaceAcquirePos) {
615             return DECODE_NO_SURFACE;
616         }
617     }
618 
619     if (acquired == false) {
620         return DECODE_NO_SURFACE;
621     }
622 
623     mAcquiredBuffer = acquiredBuffer;
624     mSurfaceAcquirePos = nextAcquire;
625 
626     // set surface again as surface maybe reset by skipped frame.
627     // skipped frame is a "non-coded frame" and decoder needs to duplicate the previous reference frame as the output.
628     mAcquiredBuffer->renderBuffer.surface = mSurfaces[mSurfaceAcquirePos];
629     if (mSurfaceUserPtr && mAcquiredBuffer->mappedData) {
630         mAcquiredBuffer->mappedData->data = mSurfaceUserPtr[mSurfaceAcquirePos];
631     }
632     mAcquiredBuffer->renderBuffer.timeStamp = INVALID_PTS;
633     mAcquiredBuffer->renderBuffer.display = mVADisplay;
634     mAcquiredBuffer->renderBuffer.flag = 0;
635     mAcquiredBuffer->renderBuffer.renderDone = false;
636     mAcquiredBuffer->asReferernce = false;
637     mAcquiredBuffer->renderBuffer.errBuf.errorNumber = 0;
638     mAcquiredBuffer->renderBuffer.errBuf.timeStamp = INVALID_PTS;
639 
640     return DECODE_SUCCESS;
641 }
642 
outputSurfaceBuffer(void)643 Decode_Status VideoDecoderBase::outputSurfaceBuffer(void) {
644     Decode_Status status;
645     if (mAcquiredBuffer == NULL) {
646         ETRACE("mAcquiredBuffer is NULL. Implementation bug.");
647         return DECODE_FAIL;
648     }
649 
650     if (mRawOutput) {
651         status = getRawDataFromSurface();
652         CHECK_STATUS();
653     }
654 
655     // frame is successfly decoded to the current surface,  it is ready for output
656     if (mShowFrame) {
657         mAcquiredBuffer->renderBuffer.renderDone = false;
658     } else {
659         mAcquiredBuffer->renderBuffer.renderDone = true;
660     }
661 
662     // decoder must set "asReference and referenceFrame" flags properly
663 
664     // update reference frames
665     if (mAcquiredBuffer->referenceFrame) {
666         if (mManageReference) {
667             // managing reference for MPEG4/H.263/WMV.
668             // AVC should manage reference frame in a different way
669             if (mForwardReference != NULL) {
670                 // this foward reference is no longer needed
671                 mForwardReference->asReferernce = false;
672             }
673             // Forware reference for either P or B frame prediction
674             mForwardReference = mLastReference;
675             mAcquiredBuffer->asReferernce = true;
676         }
677 
678         // the last reference frame.
679         mLastReference = mAcquiredBuffer;
680     }
681     // add to the output list
682     if (mShowFrame) {
683         if (mOutputHead == NULL) {
684             mOutputHead = mAcquiredBuffer;
685         } else {
686             mOutputTail->next = mAcquiredBuffer;
687         }
688         mOutputTail = mAcquiredBuffer;
689         mOutputTail->next = NULL;
690     }
691 
692     //VTRACE("Pushing POC %d to queue (pts = %.2f)", mAcquiredBuffer->pictureOrder, mAcquiredBuffer->renderBuffer.timeStamp/1E6);
693 
694     mAcquiredBuffer = NULL;
695     mSurfaceAcquirePos = (mSurfaceAcquirePos  + 1 ) % mNumSurfaces;
696     return DECODE_SUCCESS;
697 }
698 
releaseSurfaceBuffer(void)699 Decode_Status VideoDecoderBase::releaseSurfaceBuffer(void) {
700     if (mAcquiredBuffer == NULL) {
701         // this is harmless error
702         return DECODE_SUCCESS;
703     }
704 
705     // frame is not decoded to the acquired buffer, current surface is invalid, and can't be output.
706     mAcquiredBuffer->asReferernce = false;
707     mAcquiredBuffer->renderBuffer.renderDone = true;
708     mAcquiredBuffer = NULL;
709     return DECODE_SUCCESS;
710 }
711 
flushSurfaceBuffers(void)712 void VideoDecoderBase::flushSurfaceBuffers(void) {
713     endDecodingFrame(true);
714     VideoSurfaceBuffer *p = NULL;
715     while (mOutputHead) {
716         mOutputHead->renderBuffer.renderDone = true;
717         p = mOutputHead;
718         mOutputHead = mOutputHead->next;
719         p->next = NULL;
720     }
721     mOutputHead = NULL;
722     mOutputTail = NULL;
723 }
724 
endDecodingFrame(bool dropFrame)725 Decode_Status VideoDecoderBase::endDecodingFrame(bool dropFrame) {
726     Decode_Status status = DECODE_SUCCESS;
727     VAStatus vaStatus;
728 
729     if (mDecodingFrame == false) {
730         if (mAcquiredBuffer != NULL) {
731             //ETRACE("mAcquiredBuffer is not NULL. Implementation bug.");
732             releaseSurfaceBuffer();
733             status = DECODE_FAIL;
734         }
735         return status;
736     }
737     // return through exit label to reset mDecodingFrame
738     if (mAcquiredBuffer == NULL) {
739         ETRACE("mAcquiredBuffer is NULL. Implementation bug.");
740         status = DECODE_FAIL;
741         goto exit;
742     }
743 
744     vaStatus = vaEndPicture(mVADisplay, mVAContext);
745     if (vaStatus != VA_STATUS_SUCCESS) {
746         releaseSurfaceBuffer();
747         ETRACE("vaEndPicture failed. vaStatus = %d", vaStatus);
748         status = DECODE_DRIVER_FAIL;
749         goto exit;
750     }
751 
752     if (dropFrame) {
753         // we are asked to drop this decoded picture
754         VTRACE("Frame dropped in endDecodingFrame");
755         vaStatus = vaSyncSurface(mVADisplay, mAcquiredBuffer->renderBuffer.surface);
756         releaseSurfaceBuffer();
757         goto exit;
758     }
759     status = outputSurfaceBuffer();
760     // fall through
761 exit:
762     mDecodingFrame = false;
763     return status;
764 }
765 
766 
setupVA(uint32_t numSurface,VAProfile profile,uint32_t numExtraSurface)767 Decode_Status VideoDecoderBase::setupVA(uint32_t numSurface, VAProfile profile, uint32_t numExtraSurface) {
768     VAStatus vaStatus = VA_STATUS_SUCCESS;
769     Decode_Status status;
770     VAConfigAttrib attrib;
771 
772     if (mVAStarted) {
773         return DECODE_SUCCESS;
774     }
775 
776     mRotationDegrees = 0;
777     if (mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER){
778 #ifdef TARGET_HAS_VPP
779         if (mVideoFormatInfo.actualBufferNeeded > mConfigBuffer.surfaceNumber - mConfigBuffer.vppBufferNum)
780 #else
781         if (mVideoFormatInfo.actualBufferNeeded > mConfigBuffer.surfaceNumber)
782 #endif
783             return DECODE_FORMAT_CHANGE;
784 
785         numSurface = mConfigBuffer.surfaceNumber;
786         // if format has been changed in USE_NATIVE_GRAPHIC_BUFFER mode,
787         // we can not setupVA here when the graphic buffer resolution is smaller than the resolution decoder really needs
788         if (mSizeChanged) {
789             if (mVideoFormatInfo.surfaceWidth < mVideoFormatInfo.width || mVideoFormatInfo.surfaceHeight < mVideoFormatInfo.height) {
790                 mSizeChanged = false;
791                 return DECODE_FORMAT_CHANGE;
792             }
793         }
794     }
795 
796     // TODO: validate profile
797     if (numSurface == 0) {
798         return DECODE_FAIL;
799     }
800 
801     if (mConfigBuffer.flag & HAS_MINIMUM_SURFACE_NUMBER) {
802         if (numSurface < mConfigBuffer.surfaceNumber) {
803             WTRACE("surface to allocated %d is less than minimum number required %d",
804                     numSurface, mConfigBuffer.surfaceNumber);
805             numSurface = mConfigBuffer.surfaceNumber;
806         }
807     }
808 
809     if (mVADisplay != NULL) {
810         ETRACE("VA is partially started.");
811         return DECODE_FAIL;
812     }
813 
814     // Display is defined as "unsigned int"
815 #ifndef USE_HYBRID_DRIVER
816     mDisplay = new Display;
817     *mDisplay = ANDROID_DISPLAY_HANDLE;
818 #else
819     if (profile >= VAProfileH264Baseline && profile <= VAProfileVC1Advanced) {
820         ITRACE("Using GEN driver");
821         mDisplay = "libva_driver_name=i965";
822         mUseGEN = true;
823     } else {
824         ITRACE("Using PVR driver");
825         mDisplay = "libva_driver_name=pvr";
826         mUseGEN = false;
827     }
828 
829 #endif
830     mVADisplay = vaGetDisplay(mDisplay);
831     if (mVADisplay == NULL) {
832         ETRACE("vaGetDisplay failed.");
833         return DECODE_DRIVER_FAIL;
834     }
835 
836     int majorVersion, minorVersion;
837     vaStatus = vaInitialize(mVADisplay, &majorVersion, &minorVersion);
838     CHECK_VA_STATUS("vaInitialize");
839 
840     if ((int32_t)profile != VAProfileSoftwareDecoding) {
841 
842         status = checkHardwareCapability();
843         CHECK_STATUS("checkHardwareCapability");
844 
845 #if (defined USE_AVC_SHORT_FORMAT || defined USE_SLICE_HEADER_PARSING)
846         status = getCodecSpecificConfigs(profile, &mVAConfig);
847         CHECK_STATUS("getCodecSpecificAttributes");
848 #else
849         //We are requesting RT attributes
850         attrib.type = VAConfigAttribRTFormat;
851         attrib.value = VA_RT_FORMAT_YUV420;
852 
853         vaStatus = vaCreateConfig(
854                 mVADisplay,
855                 profile,
856                 VAEntrypointVLD,
857                 &attrib,
858                 1,
859                 &mVAConfig);
860         CHECK_VA_STATUS("vaCreateConfig");
861 #endif
862     }
863 
864     mNumSurfaces = numSurface;
865     mNumExtraSurfaces = numExtraSurface;
866     mSurfaces = new VASurfaceID [mNumSurfaces + mNumExtraSurfaces];
867     mExtraSurfaces = mSurfaces + mNumSurfaces;
868     if (mSurfaces == NULL) {
869         return DECODE_MEMORY_FAIL;
870     }
871 
872     setRenderRect();
873 
874     int32_t format = VA_RT_FORMAT_YUV420;
875     if (mConfigBuffer.flag & WANT_SURFACE_PROTECTION) {
876 #ifndef USE_AVC_SHORT_FORMAT
877         format |= VA_RT_FORMAT_PROTECTED;
878         WTRACE("Surface is protected.");
879 #endif
880     }
881     if (mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER) {
882         VASurfaceAttrib attribs[2];
883         mVASurfaceAttrib = new VASurfaceAttribExternalBuffers;
884         if (mVASurfaceAttrib == NULL) {
885             return DECODE_MEMORY_FAIL;
886         }
887 
888         mVASurfaceAttrib->buffers= (unsigned long *)malloc(sizeof(unsigned long)*mNumSurfaces);
889         if (mVASurfaceAttrib->buffers == NULL) {
890             return DECODE_MEMORY_FAIL;
891         }
892         mVASurfaceAttrib->num_buffers = mNumSurfaces;
893         mVASurfaceAttrib->pixel_format = VA_FOURCC_NV12;
894         mVASurfaceAttrib->width = mVideoFormatInfo.surfaceWidth;
895         mVASurfaceAttrib->height = mVideoFormatInfo.surfaceHeight;
896         mVASurfaceAttrib->data_size = mConfigBuffer.graphicBufferStride * mVideoFormatInfo.surfaceHeight * 1.5;
897         mVASurfaceAttrib->num_planes = 2;
898         mVASurfaceAttrib->pitches[0] = mConfigBuffer.graphicBufferStride;
899         mVASurfaceAttrib->pitches[1] = mConfigBuffer.graphicBufferStride;
900         mVASurfaceAttrib->pitches[2] = 0;
901         mVASurfaceAttrib->pitches[3] = 0;
902         mVASurfaceAttrib->offsets[0] = 0;
903         mVASurfaceAttrib->offsets[1] = mConfigBuffer.graphicBufferStride * mVideoFormatInfo.surfaceHeight;
904         mVASurfaceAttrib->offsets[2] = 0;
905         mVASurfaceAttrib->offsets[3] = 0;
906         mVASurfaceAttrib->private_data = (void *)mConfigBuffer.nativeWindow;
907         mVASurfaceAttrib->flags = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
908         if (mConfigBuffer.flag & USE_TILING_MEMORY)
909             mVASurfaceAttrib->flags |= VA_SURFACE_EXTBUF_DESC_ENABLE_TILING;
910 
911         for (int i = 0; i < mNumSurfaces; i++) {
912             mVASurfaceAttrib->buffers[i] = (unsigned long)mConfigBuffer.graphicBufferHandler[i];
913         }
914 
915         attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType;
916         attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
917         attribs[0].value.type = VAGenericValueTypeInteger;
918         attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
919 
920         attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor;
921         attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
922         attribs[1].value.type = VAGenericValueTypePointer;
923         attribs[1].value.value.p = (void *)mVASurfaceAttrib;
924 
925         vaStatus = vaCreateSurfaces(
926             mVADisplay,
927             format,
928             mVideoFormatInfo.surfaceWidth,
929             mVideoFormatInfo.surfaceHeight,
930             mSurfaces,
931             mNumSurfaces,
932             attribs,
933             2);
934 
935     } else {
936         vaStatus = vaCreateSurfaces(
937             mVADisplay,
938             format,
939             mVideoFormatInfo.width,
940             mVideoFormatInfo.height,
941             mSurfaces,
942             mNumSurfaces,
943             NULL,
944             0);
945         mVideoFormatInfo.surfaceWidth = mVideoFormatInfo.width;
946         mVideoFormatInfo.surfaceHeight = mVideoFormatInfo.height;
947     }
948     CHECK_VA_STATUS("vaCreateSurfaces");
949 
950     if (mNumExtraSurfaces != 0) {
951         vaStatus = vaCreateSurfaces(
952             mVADisplay,
953             format,
954             mVideoFormatInfo.surfaceWidth,
955             mVideoFormatInfo.surfaceHeight,
956             mExtraSurfaces,
957             mNumExtraSurfaces,
958             NULL,
959             0);
960         CHECK_VA_STATUS("vaCreateSurfaces");
961     }
962 
963     mVideoFormatInfo.surfaceNumber = mNumSurfaces;
964     mVideoFormatInfo.ctxSurfaces = mSurfaces;
965 
966     if ((int32_t)profile != VAProfileSoftwareDecoding) {
967         vaStatus = vaCreateContext(
968                 mVADisplay,
969                 mVAConfig,
970                 mVideoFormatInfo.surfaceWidth,
971                 mVideoFormatInfo.surfaceHeight,
972                 0,
973                 mSurfaces,
974                 mNumSurfaces + mNumExtraSurfaces,
975                 &mVAContext);
976         CHECK_VA_STATUS("vaCreateContext");
977     }
978 
979     mSurfaceBuffers = new VideoSurfaceBuffer [mNumSurfaces];
980     if (mSurfaceBuffers == NULL) {
981         return DECODE_MEMORY_FAIL;
982     }
983     initSurfaceBuffer(true);
984 
985     if ((int32_t)profile == VAProfileSoftwareDecoding) {
986         // derive user pointer from surface for direct access
987         status = mapSurface();
988         CHECK_STATUS("mapSurface")
989     }
990 
991     setRotationDegrees(mConfigBuffer.rotationDegrees);
992 
993     mVAStarted = true;
994     return DECODE_SUCCESS;
995 }
996 
terminateVA(void)997 Decode_Status VideoDecoderBase::terminateVA(void) {
998     mSignalBufferSize = 0;
999     for (int i = 0; i < MAX_GRAPHIC_BUFFER_NUM; i++) {
1000          mSignalBufferPre[i] = NULL;
1001     }
1002 
1003     if (mVAStarted == false) {
1004         // VA hasn't been started yet
1005         return DECODE_SUCCESS;
1006     }
1007 
1008     if (mSurfaceBuffers) {
1009         for (int32_t i = 0; i < mNumSurfaces; i++) {
1010             if (mSurfaceBuffers[i].renderBuffer.rawData) {
1011                 if (mSurfaceBuffers[i].renderBuffer.rawData->data) {
1012                     delete [] mSurfaceBuffers[i].renderBuffer.rawData->data;
1013                 }
1014                 delete mSurfaceBuffers[i].renderBuffer.rawData;
1015             }
1016             if (mSurfaceBuffers[i].mappedData) {
1017                 // don't  delete data pointer as it is mapped from surface
1018                 delete mSurfaceBuffers[i].mappedData;
1019             }
1020         }
1021         delete [] mSurfaceBuffers;
1022         mSurfaceBuffers = NULL;
1023     }
1024 
1025     if (mVASurfaceAttrib) {
1026         if (mVASurfaceAttrib->buffers) free(mVASurfaceAttrib->buffers);
1027         delete mVASurfaceAttrib;
1028         mVASurfaceAttrib = NULL;
1029     }
1030 
1031 
1032     if (mSurfaceUserPtr) {
1033         delete [] mSurfaceUserPtr;
1034         mSurfaceUserPtr = NULL;
1035     }
1036 
1037     if (mSurfaces)
1038     {
1039         vaDestroySurfaces(mVADisplay, mSurfaces, mNumSurfaces + mNumExtraSurfaces);
1040         delete [] mSurfaces;
1041         mSurfaces = NULL;
1042     }
1043 
1044     if (mVAContext != VA_INVALID_ID) {
1045          vaDestroyContext(mVADisplay, mVAContext);
1046          mVAContext = VA_INVALID_ID;
1047     }
1048 
1049     if (mVAConfig != VA_INVALID_ID) {
1050         vaDestroyConfig(mVADisplay, mVAConfig);
1051         mVAConfig = VA_INVALID_ID;
1052     }
1053 
1054     if (mVADisplay) {
1055         vaTerminate(mVADisplay);
1056         mVADisplay = NULL;
1057     }
1058 
1059     if (mDisplay) {
1060 #ifndef USE_HYBRID_DRIVER
1061         delete mDisplay;
1062 #endif
1063         mDisplay = NULL;
1064     }
1065 
1066     mVAStarted = false;
1067     mInitialized = false;
1068     mErrReportEnabled = false;
1069     return DECODE_SUCCESS;
1070 }
1071 
parseBuffer(uint8_t * buffer,int32_t size,bool config,void ** vbpData)1072 Decode_Status VideoDecoderBase::parseBuffer(uint8_t *buffer, int32_t size, bool config, void** vbpData) {
1073      // DON'T check if mVAStarted == true
1074     if (mParserHandle == NULL) {
1075         return DECODE_NO_PARSER;
1076     }
1077 
1078     uint32_t vbpStatus;
1079     if (buffer == NULL || size <= 0) {
1080         return DECODE_INVALID_DATA;
1081     }
1082 
1083     uint8_t configFlag = config ? 1 : 0;
1084     vbpStatus = mParserParse(mParserHandle, buffer, size, configFlag);
1085     CHECK_VBP_STATUS("vbp_parse");
1086 
1087     vbpStatus = mParserQuery(mParserHandle, vbpData);
1088     CHECK_VBP_STATUS("vbp_query");
1089 
1090     return DECODE_SUCCESS;
1091 }
1092 
1093 
1094 
mapSurface(void)1095 Decode_Status VideoDecoderBase::mapSurface(void) {
1096     VAStatus vaStatus = VA_STATUS_SUCCESS;
1097     VAImage image;
1098     uint8_t *userPtr;
1099     mSurfaceUserPtr = new uint8_t* [mNumSurfaces];
1100     if (mSurfaceUserPtr == NULL) {
1101         return DECODE_MEMORY_FAIL;
1102     }
1103 
1104     for (int32_t i = 0; i< mNumSurfaces; i++) {
1105         vaStatus = vaDeriveImage(mVADisplay, mSurfaces[i], &image);
1106         CHECK_VA_STATUS("vaDeriveImage");
1107         vaStatus = vaMapBuffer(mVADisplay, image.buf, (void**)&userPtr);
1108         CHECK_VA_STATUS("vaMapBuffer");
1109         mSurfaceUserPtr[i] = userPtr;
1110         mSurfaceBuffers[i].mappedData = new VideoFrameRawData;
1111         if (mSurfaceBuffers[i].mappedData == NULL) {
1112             return DECODE_MEMORY_FAIL;
1113         }
1114         mSurfaceBuffers[i].mappedData->own = false; // derived from surface so can't be released
1115         mSurfaceBuffers[i].mappedData->data = NULL;  // specified during acquireSurfaceBuffer
1116         mSurfaceBuffers[i].mappedData->fourcc = image.format.fourcc;
1117         mSurfaceBuffers[i].mappedData->width = mVideoFormatInfo.width;
1118         mSurfaceBuffers[i].mappedData->height = mVideoFormatInfo.height;
1119         mSurfaceBuffers[i].mappedData->size = image.data_size;
1120         for (int pi = 0; pi < 3; pi++) {
1121             mSurfaceBuffers[i].mappedData->pitch[pi] = image.pitches[pi];
1122             mSurfaceBuffers[i].mappedData->offset[pi] = image.offsets[pi];
1123         }
1124         // debug information
1125         if (image.pitches[0] != image.pitches[1] ||
1126             image.width != mVideoFormatInfo.width ||
1127             image.height != mVideoFormatInfo.height ||
1128             image.offsets[0] != 0) {
1129             WTRACE("Unexpected VAImage format, w = %d, h = %d, offset = %d", image.width, image.height, image.offsets[0]);
1130         }
1131         // TODO: do we need to unmap buffer?
1132         //vaStatus = vaUnmapBuffer(mVADisplay, image.buf);
1133         //CHECK_VA_STATUS("vaMapBuffer");
1134         vaStatus = vaDestroyImage(mVADisplay,image.image_id);
1135         CHECK_VA_STATUS("vaDestroyImage");
1136 
1137     }
1138     return DECODE_SUCCESS;
1139 }
1140 
getRawDataFromSurface(VideoRenderBuffer * renderBuffer,uint8_t * pRawData,uint32_t * pSize,bool internal)1141 Decode_Status VideoDecoderBase::getRawDataFromSurface(VideoRenderBuffer *renderBuffer, uint8_t *pRawData, uint32_t *pSize, bool internal) {
1142     if (internal) {
1143         if (mAcquiredBuffer == NULL) {
1144             return DECODE_FAIL;
1145         }
1146         renderBuffer = &(mAcquiredBuffer->renderBuffer);
1147     }
1148 
1149     VAStatus vaStatus;
1150     VAImageFormat imageFormat;
1151     VAImage vaImage;
1152     vaStatus = vaSyncSurface(renderBuffer->display, renderBuffer->surface);
1153     CHECK_VA_STATUS("vaSyncSurface");
1154 
1155     vaStatus = vaDeriveImage(renderBuffer->display, renderBuffer->surface, &vaImage);
1156     CHECK_VA_STATUS("vaDeriveImage");
1157 
1158     void *pBuf = NULL;
1159     vaStatus = vaMapBuffer(renderBuffer->display, vaImage.buf, &pBuf);
1160     CHECK_VA_STATUS("vaMapBuffer");
1161 
1162 
1163     // size in NV12 format
1164     uint32_t cropWidth = mVideoFormatInfo.width - (mVideoFormatInfo.cropLeft + mVideoFormatInfo.cropRight);
1165     uint32_t cropHeight = mVideoFormatInfo.height - (mVideoFormatInfo.cropBottom + mVideoFormatInfo.cropTop);
1166     int32_t size = cropWidth  * cropHeight * 3 / 2;
1167 
1168     if (internal) {
1169         VideoFrameRawData *rawData = NULL;
1170         if (renderBuffer->rawData == NULL) {
1171             rawData = new VideoFrameRawData;
1172             if (rawData == NULL) {
1173                 return DECODE_MEMORY_FAIL;
1174             }
1175             memset(rawData, 0, sizeof(VideoFrameRawData));
1176             renderBuffer->rawData = rawData;
1177         } else {
1178             rawData = renderBuffer->rawData;
1179         }
1180 
1181         if (rawData->data != NULL && rawData->size != size) {
1182             delete [] rawData->data;
1183             rawData->data = NULL;
1184             rawData->size = 0;
1185         }
1186         if (rawData->data == NULL) {
1187             rawData->data = new uint8_t [size];
1188             if (rawData->data == NULL) {
1189                 return DECODE_MEMORY_FAIL;
1190             }
1191         }
1192 
1193         rawData->own = true; // allocated by this library
1194         rawData->width = cropWidth;
1195         rawData->height = cropHeight;
1196         rawData->pitch[0] = cropWidth;
1197         rawData->pitch[1] = cropWidth;
1198         rawData->pitch[2] = 0;  // interleaved U/V, two planes
1199         rawData->offset[0] = 0;
1200         rawData->offset[1] = cropWidth * cropHeight;
1201         rawData->offset[2] = cropWidth * cropHeight * 3 / 2;
1202         rawData->size = size;
1203         rawData->fourcc = 'NV12';
1204 
1205         pRawData = rawData->data;
1206     } else {
1207         *pSize = size;
1208     }
1209 
1210     if (size == (int32_t)vaImage.data_size) {
1211 #ifdef  __SSE4_1__
1212         stream_memcpy(pRawData, pBuf, size);
1213 #else
1214         memcpy(pRawData, pBuf, size);
1215 #endif
1216     } else {
1217         // copy Y data
1218         uint8_t *src = (uint8_t*)pBuf;
1219         uint8_t *dst = pRawData;
1220         uint32_t row = 0;
1221         for (row = 0; row < cropHeight; row++) {
1222 #ifdef  __SSE4_1__
1223             stream_memcpy(dst, src, cropWidth);
1224 #else
1225             memcpy(dst, src, cropWidth);
1226 #endif
1227             dst += cropWidth;
1228             src += vaImage.pitches[0];
1229         }
1230         // copy interleaved V and  U data
1231         src = (uint8_t*)pBuf + vaImage.offsets[1];
1232         for (row = 0; row < cropHeight / 2; row++) {
1233 #ifdef  __SSE4_1__
1234             stream_memcpy(dst, src, cropWidth);
1235 #else
1236             memcpy(dst, src, cropWidth);
1237 #endif
1238             dst += cropWidth;
1239             src += vaImage.pitches[1];
1240         }
1241     }
1242 
1243     vaStatus = vaUnmapBuffer(renderBuffer->display, vaImage.buf);
1244     CHECK_VA_STATUS("vaUnmapBuffer");
1245 
1246     vaStatus = vaDestroyImage(renderBuffer->display, vaImage.image_id);
1247     CHECK_VA_STATUS("vaDestroyImage");
1248 
1249     return DECODE_SUCCESS;
1250 }
1251 
initSurfaceBuffer(bool reset)1252 void VideoDecoderBase::initSurfaceBuffer(bool reset) {
1253     bool useGraphicBuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
1254     if (useGraphicBuffer && reset) {
1255         pthread_mutex_lock(&mLock);
1256     }
1257     for (int32_t i = 0; i < mNumSurfaces; i++) {
1258         mSurfaceBuffers[i].renderBuffer.display = mVADisplay;
1259         mSurfaceBuffers[i].renderBuffer.surface = VA_INVALID_SURFACE;  // set in acquireSurfaceBuffer
1260         mSurfaceBuffers[i].renderBuffer.flag = 0;
1261         mSurfaceBuffers[i].renderBuffer.scanFormat = VA_FRAME_PICTURE;
1262         mSurfaceBuffers[i].renderBuffer.timeStamp = 0;
1263         mSurfaceBuffers[i].referenceFrame = false;
1264         mSurfaceBuffers[i].asReferernce= false;
1265         mSurfaceBuffers[i].pictureOrder = 0;
1266         mSurfaceBuffers[i].next = NULL;
1267         if (reset == true) {
1268             mSurfaceBuffers[i].renderBuffer.rawData = NULL;
1269             mSurfaceBuffers[i].mappedData = NULL;
1270         }
1271         if (useGraphicBuffer) {
1272             if (reset) {
1273                mSurfaceBuffers[i].renderBuffer.graphicBufferHandle = mConfigBuffer.graphicBufferHandler[i];
1274                mSurfaceBuffers[i].renderBuffer.renderDone = false; //default false
1275                for (uint32_t j = 0; j < mSignalBufferSize; j++) {
1276                    if(mSignalBufferPre[j] != NULL && mSignalBufferPre[j] == mSurfaceBuffers[i].renderBuffer.graphicBufferHandle) {
1277                       mSurfaceBuffers[i].renderBuffer.renderDone = true;
1278                       VTRACE("initSurfaceBuffer set renderDone = true index = %d", i);
1279                       mSignalBufferPre[j] = NULL;
1280                       break;
1281                    }
1282                }
1283             } else {
1284                mSurfaceBuffers[i].renderBuffer.renderDone = false;
1285             }
1286         } else {
1287             mSurfaceBuffers[i].renderBuffer.graphicBufferHandle = NULL;
1288             mSurfaceBuffers[i].renderBuffer.renderDone = true;
1289         }
1290         mSurfaceBuffers[i].renderBuffer.graphicBufferIndex = i;
1291     }
1292 
1293     if (useGraphicBuffer && reset) {
1294         mInitialized = true;
1295         mSignalBufferSize = 0;
1296         pthread_mutex_unlock(&mLock);
1297     }
1298 }
1299 
signalRenderDone(void * graphichandler)1300 Decode_Status VideoDecoderBase::signalRenderDone(void * graphichandler) {
1301     if (graphichandler == NULL) {
1302         return DECODE_SUCCESS;
1303     }
1304     pthread_mutex_lock(&mLock);
1305     int i = 0;
1306     if (!mInitialized) {
1307         if (mSignalBufferSize >= MAX_GRAPHIC_BUFFER_NUM) {
1308             pthread_mutex_unlock(&mLock);
1309             return DECODE_INVALID_DATA;
1310         }
1311         mSignalBufferPre[mSignalBufferSize++] = graphichandler;
1312         VTRACE("SignalRenderDoneFlag mInitialized = false graphichandler = %p, mSignalBufferSize = %d", graphichandler, mSignalBufferSize);
1313     } else {
1314         if (!(mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER)) {
1315             pthread_mutex_unlock(&mLock);
1316             return DECODE_SUCCESS;
1317         }
1318         for (i = 0; i < mNumSurfaces; i++) {
1319             if (mSurfaceBuffers[i].renderBuffer.graphicBufferHandle == graphichandler) {
1320                 mSurfaceBuffers[i].renderBuffer.renderDone = true;
1321                 VTRACE("SignalRenderDoneFlag mInitialized = true index = %d", i);
1322                break;
1323            }
1324         }
1325     }
1326     pthread_mutex_unlock(&mLock);
1327 
1328     return DECODE_SUCCESS;
1329 
1330 }
1331 
querySurfaceRenderStatus(VideoSurfaceBuffer * surface)1332 void VideoDecoderBase::querySurfaceRenderStatus(VideoSurfaceBuffer* surface) {
1333     VASurfaceStatus surfStat = VASurfaceReady;
1334     VAStatus    vaStat = VA_STATUS_SUCCESS;
1335 
1336     if (!surface) {
1337         LOGW("SurfaceBuffer not ready yet");
1338         return;
1339     }
1340     surface->renderBuffer.driverRenderDone = true;
1341 
1342 #ifndef USE_GEN_HW
1343     if (surface->renderBuffer.surface != VA_INVALID_SURFACE &&
1344        (mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER)) {
1345 
1346         vaStat = vaQuerySurfaceStatus(mVADisplay, surface->renderBuffer.surface, &surfStat);
1347 
1348         if ((vaStat == VA_STATUS_SUCCESS) && (surfStat != VASurfaceReady))
1349             surface->renderBuffer.driverRenderDone = false;
1350 
1351     }
1352 #endif
1353 
1354 }
1355 
1356 // This function should be called before start() to load different type of parsers
1357 #if (defined USE_AVC_SHORT_FORMAT || defined USE_SLICE_HEADER_PARSING)
setParserType(_vbp_parser_type type)1358 Decode_Status VideoDecoderBase::setParserType(_vbp_parser_type type) {
1359     if ((int32_t)type != VBP_INVALID) {
1360         ITRACE("Parser Type = %d", (int32_t)type);
1361         mParserType = type;
1362         return DECODE_SUCCESS;
1363     } else {
1364         ETRACE("Invalid parser type = %d", (int32_t)type);
1365         return DECODE_NO_PARSER;
1366     }
1367 }
1368 
updateBuffer(uint8_t * buffer,int32_t size,void ** vbpData)1369 Decode_Status VideoDecoderBase::updateBuffer(uint8_t *buffer, int32_t size, void** vbpData) {
1370     if (mParserHandle == NULL) {
1371         return DECODE_NO_PARSER;
1372     }
1373 
1374     uint32_t vbpStatus;
1375     if (buffer == NULL || size <= 0) {
1376         return DECODE_INVALID_DATA;
1377     }
1378 
1379     vbpStatus = mParserUpdate(mParserHandle, buffer, size, vbpData);
1380     CHECK_VBP_STATUS("vbp_update");
1381 
1382     return DECODE_SUCCESS;
1383 }
1384 
queryBuffer(void ** vbpData)1385 Decode_Status VideoDecoderBase::queryBuffer(void** vbpData) {
1386     if (mParserHandle == NULL) {
1387         return DECODE_NO_PARSER;
1388     }
1389 
1390     uint32_t vbpStatus;
1391     vbpStatus = mParserQuery(mParserHandle, vbpData);
1392     CHECK_VBP_STATUS("vbp_query");
1393 
1394     return DECODE_SUCCESS;
1395 }
1396 
getCodecSpecificConfigs(VAProfile profile,VAConfigID * config)1397 Decode_Status VideoDecoderBase::getCodecSpecificConfigs(VAProfile profile, VAConfigID *config) {
1398     VAStatus vaStatus;
1399     VAConfigAttrib attrib;
1400     attrib.type = VAConfigAttribRTFormat;
1401     attrib.value = VA_RT_FORMAT_YUV420;
1402 
1403     if (config == NULL) {
1404         ETRACE("Invalid parameter!");
1405         return DECODE_FAIL;
1406     }
1407 
1408     vaStatus = vaCreateConfig(
1409             mVADisplay,
1410             profile,
1411             VAEntrypointVLD,
1412             &attrib,
1413             1,
1414             config);
1415 
1416     CHECK_VA_STATUS("vaCreateConfig");
1417 
1418     return DECODE_SUCCESS;
1419 }
1420 #endif
checkHardwareCapability()1421 Decode_Status VideoDecoderBase::checkHardwareCapability() {
1422     return DECODE_SUCCESS;
1423 }
1424 
drainDecodingErrors(VideoErrorBuffer * outErrBuf,VideoRenderBuffer * currentSurface)1425 void VideoDecoderBase::drainDecodingErrors(VideoErrorBuffer *outErrBuf, VideoRenderBuffer *currentSurface) {
1426     if (mErrReportEnabled && outErrBuf && currentSurface) {
1427         memcpy(outErrBuf, &(currentSurface->errBuf), sizeof(VideoErrorBuffer));
1428 
1429         currentSurface->errBuf.errorNumber = 0;
1430         currentSurface->errBuf.timeStamp = INVALID_PTS;
1431     }
1432     if (outErrBuf)
1433         VTRACE("%s: error number is %d", __FUNCTION__, outErrBuf->errorNumber);
1434 }
1435 
fillDecodingErrors(VideoRenderBuffer * currentSurface)1436 void VideoDecoderBase::fillDecodingErrors(VideoRenderBuffer *currentSurface) {
1437     VAStatus ret;
1438 
1439     if (mErrReportEnabled) {
1440         currentSurface->errBuf.timeStamp = currentSurface->timeStamp;
1441         // TODO: is 10 a suitable number?
1442         VASurfaceDecodeMBErrors *err_drv_output = NULL;
1443         ret = vaQuerySurfaceError(mVADisplay, currentSurface->surface, VA_STATUS_ERROR_DECODING_ERROR, (void **)&err_drv_output);
1444         if (ret || !err_drv_output) {
1445             WTRACE("vaQuerySurfaceError failed.");
1446             return;
1447         }
1448 
1449         int offset =  0x1 & currentSurface->errBuf.errorNumber;// offset is either 0 or 1
1450         for (int i = 0; i < MAX_ERR_NUM - offset; i++) {
1451             if (err_drv_output[i].status != -1) {
1452                 currentSurface->errBuf.errorNumber++;
1453                 currentSurface->errBuf.errorArray[i + offset].type = DecodeMBError;
1454                 currentSurface->errBuf.errorArray[i + offset].error_data.mb_pos.start_mb = err_drv_output[i].start_mb;
1455                 currentSurface->errBuf.errorArray[i + offset].error_data.mb_pos.end_mb = err_drv_output[i].end_mb;
1456                 currentSurface->errBuf.errorArray[i + offset].num_mbs = err_drv_output[i].end_mb - err_drv_output[i].start_mb + 1;
1457                 ITRACE("Error Index[%d]: type = %d, start_mb = %d, end_mb = %d",
1458                     currentSurface->errBuf.errorNumber - 1,
1459                     currentSurface->errBuf.errorArray[i + offset].type,
1460                     currentSurface->errBuf.errorArray[i + offset].error_data.mb_pos.start_mb,
1461                     currentSurface->errBuf.errorArray[i + offset].error_data.mb_pos.end_mb);
1462             } else break;
1463         }
1464         ITRACE("%s: error number of current surface is %d, timestamp @%llu",
1465             __FUNCTION__, currentSurface->errBuf.errorNumber, currentSurface->timeStamp);
1466     }
1467 }
1468 
setRotationDegrees(int32_t rotationDegrees)1469 void VideoDecoderBase::setRotationDegrees(int32_t rotationDegrees) {
1470     if (mRotationDegrees == rotationDegrees) {
1471         return;
1472     }
1473 
1474     ITRACE("set new rotation degree: %d", rotationDegrees);
1475     VADisplayAttribute rotate;
1476     rotate.type = VADisplayAttribRotation;
1477     rotate.value = VA_ROTATION_NONE;
1478     if (rotationDegrees == 0)
1479         rotate.value = VA_ROTATION_NONE;
1480     else if (rotationDegrees == 90)
1481         rotate.value = VA_ROTATION_90;
1482     else if (rotationDegrees == 180)
1483         rotate.value = VA_ROTATION_180;
1484     else if (rotationDegrees == 270)
1485         rotate.value = VA_ROTATION_270;
1486 
1487     VAStatus ret = vaSetDisplayAttributes(mVADisplay, &rotate, 1);
1488     if (ret) {
1489         ETRACE("Failed to set rotation degree.");
1490     }
1491     mRotationDegrees = rotationDegrees;
1492 }
1493 
setRenderRect()1494 void VideoDecoderBase::setRenderRect() {
1495 
1496     if (!mVADisplay)
1497         return;
1498 
1499     VAStatus ret;
1500     VARectangle rect;
1501     rect.x = mVideoFormatInfo.cropLeft;
1502     rect.y = mVideoFormatInfo.cropTop;
1503     rect.width = mVideoFormatInfo.width - (mVideoFormatInfo.cropLeft + mVideoFormatInfo.cropRight);
1504     rect.height = mVideoFormatInfo.height - (mVideoFormatInfo.cropBottom + mVideoFormatInfo.cropTop);
1505 
1506     VADisplayAttribute render_rect;
1507     render_rect.type = VADisplayAttribRenderRect;
1508     render_rect.value = (long)&rect;
1509 
1510     ret = vaSetDisplayAttributes(mVADisplay, &render_rect, 1);
1511     if (ret) {
1512         ETRACE("Failed to set rotation degree.");
1513     }
1514 }
1515