DVDCodecs: Amlogic: Handle conditions in which amcodec should be opened during Open()
[vuplus_xbmc] / xbmc / cores / dvdplayer / DVDCodecs / Video / libstagefrightICS / StageFrightVideo.cpp
1 /*
2  *      Copyright (C) 2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20 /***************************************************************************/
21
22 //#define DEBUG_VERBOSE 1
23
24 #include "system.h"
25 #include "system_gl.h"
26
27 #include "StageFrightVideo.h"
28 #include "StageFrightVideoPrivate.h"
29
30 #include "guilib/GraphicContext.h"
31 #include "DVDClock.h"
32 #include "utils/log.h"
33 #include "utils/fastmemcpy.h"
34 #include "threads/Thread.h"
35 #include "threads/Event.h"
36 #include "Application.h"
37 #include "ApplicationMessenger.h"
38 #include "settings/AdvancedSettings.h"
39 #include "android/jni/Build.h"
40
41 #include "xbmc/guilib/FrameBufferObject.h"
42
43 #include <EGL/egl.h>
44 #include <EGL/eglext.h>
45 #include "windowing/egl/EGLWrapper.h"
46 #include "windowing/WindowingFactory.h"
47
48 #include <new>
49
50 #define OMX_QCOM_COLOR_FormatYVU420SemiPlanar 0x7FA30C00
51 #define OMX_TI_COLOR_FormatYUV420PackedSemiPlanar 0x7F000100
52
53 #define CLASSNAME "CStageFrightVideo"
54
55 #define EGL_NATIVE_BUFFER_ANDROID 0x3140
56 #define EGL_IMAGE_PRESERVED_KHR   0x30D2
57
58 using namespace android;
59
60 static int64_t pts_dtoi(double pts)
61 {
62   return (int64_t)(pts);
63 }
64
65 static double pts_itod(int64_t pts)
66 {
67   return (double)pts;
68 }
69
70 /***********************************************************/
71
72 class CStageFrightMediaSource : public MediaSource
73 {
74 public:
75   CStageFrightMediaSource(CStageFrightVideoPrivate *priv, sp<MetaData> meta)
76   {
77     p = priv;
78     source_meta = meta;
79   }
80
81   virtual sp<MetaData> getFormat()
82   {
83     return source_meta;
84   }
85
86   virtual status_t start(MetaData *params)
87   {
88     return OK;
89   }
90
91   virtual status_t stop()
92   {
93     return OK;
94   }
95
96   virtual status_t read(MediaBuffer **buffer,
97                         const MediaSource::ReadOptions *options)
98   {
99     Frame *frame;
100     status_t ret;
101     *buffer = NULL;
102     int64_t time_us = -1;
103     MediaSource::ReadOptions::SeekMode mode;
104
105     if (options && options->getSeekTo(&time_us, &mode))
106     {
107 #if defined(DEBUG_VERBOSE)
108       CLog::Log(LOGDEBUG, "%s: reading source(%d): seek:%llu\n", CLASSNAME,p->in_queue.size(), time_us);
109 #endif
110     }
111     else
112     {
113 #if defined(DEBUG_VERBOSE)
114       CLog::Log(LOGDEBUG, "%s: reading source(%d)\n", CLASSNAME,p->in_queue.size());
115 #endif
116     }
117
118     p->in_mutex.lock();
119     while (p->in_queue.empty() && p->decode_thread)
120       p->in_condition.wait(p->in_mutex);
121
122     if (p->in_queue.empty())
123     {
124       p->in_mutex.unlock();
125       return VC_ERROR;
126     }
127
128     std::list<Frame*>::iterator it = p->in_queue.begin();
129     frame = *it;
130     ret = frame->status;
131     *buffer = frame->medbuf;
132
133     p->in_queue.erase(it);
134     p->in_mutex.unlock();
135
136 #if defined(DEBUG_VERBOSE)
137     CLog::Log(LOGDEBUG, ">>> exiting reading source(%d); pts:%llu\n", p->in_queue.size(),frame->pts);
138 #endif
139
140     free(frame);
141
142     return ret;
143   }
144
145 private:
146   sp<MetaData> source_meta;
147   CStageFrightVideoPrivate *p;
148 };
149
150 /********************************************/
151
152 class CStageFrightDecodeThread : public CThread
153 {
154 protected:
155   CStageFrightVideoPrivate *p;
156
157 public:
158   CStageFrightDecodeThread(CStageFrightVideoPrivate *priv)
159   : CThread("CStageFrightDecodeThread")
160   , p(priv)
161   {}
162
163   void OnStartup()
164   {
165   #if defined(DEBUG_VERBOSE)
166     CLog::Log(LOGDEBUG, "%s: entering decode thread\n", CLASSNAME);
167   #endif
168   }
169
170   void OnExit()
171   {
172   #if defined(DEBUG_VERBOSE)
173     CLog::Log(LOGDEBUG, "%s: exited decode thread\n", CLASSNAME);
174   #endif
175   }
176
177   void Process()
178   {
179     Frame* frame;
180     int32_t w, h;
181     int decode_done = 0;
182     MediaSource::ReadOptions readopt;
183     // GLuint texid;
184
185     //SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
186     do
187     {
188       #if defined(DEBUG_VERBOSE)
189       unsigned int time = XbmcThreads::SystemClockMillis();
190       CLog::Log(LOGDEBUG, "%s: >>> Handling frame\n", CLASSNAME);
191       #endif
192       p->cur_frame = NULL;
193       frame = (Frame*)malloc(sizeof(Frame));
194       if (!frame)
195       {
196         decode_done   = 1;
197         continue;
198       }
199
200       frame->eglimg = EGL_NO_IMAGE_KHR;
201       frame->medbuf = NULL;
202       if (p->resetting)
203       {
204         readopt.setSeekTo(0);
205         p->resetting = false;
206       }
207       frame->status = p->decoder->read(&frame->medbuf, &readopt);
208       readopt.clearSeekTo();
209
210       if (frame->status == OK)
211       {
212         if (!frame->medbuf->graphicBuffer().get())  // hw buffers
213         {
214           if (frame->medbuf->range_length() == 0)
215           {
216             CLog::Log(LOGERROR, "%s - Invalid buffer\n", CLASSNAME);
217             frame->status = VC_ERROR;
218             decode_done   = 1;
219             frame->medbuf->release();
220             frame->medbuf = NULL;
221           }
222           else
223             frame->format = RENDER_FMT_YUV420P;
224         }
225         else
226           frame->format = RENDER_FMT_EGLIMG;
227       }
228
229       if (frame->status == OK)
230       {
231         frame->width = p->width;
232         frame->height = p->height;
233         frame->pts = 0;
234
235         sp<MetaData> outFormat = p->decoder->getFormat();
236         outFormat->findInt32(kKeyWidth , &w);
237         outFormat->findInt32(kKeyHeight, &h);
238         frame->medbuf->meta_data()->findInt64(kKeyTime, &(frame->pts));
239       }
240       else if (frame->status == INFO_FORMAT_CHANGED)
241       {
242         int32_t cropLeft, cropTop, cropRight, cropBottom;
243         sp<MetaData> outFormat = p->decoder->getFormat();
244
245         outFormat->findInt32(kKeyWidth , &p->width);
246         outFormat->findInt32(kKeyHeight, &p->height);
247
248         cropLeft = cropTop = cropRight = cropBottom = 0;
249         if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
250         {
251           p->x = 0;
252           p->y = 0;
253         }
254         else
255         {
256           p->x = cropLeft;
257           p->y = cropTop;
258           p->width = cropRight - cropLeft + 1;
259           p->height = cropBottom - cropTop + 1;
260         }
261         outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat);
262         if (!outFormat->findInt32(kKeyStride, &p->videoStride))
263           p->videoStride = p->width;
264         if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
265           p->videoSliceHeight = p->height;
266
267 #if defined(DEBUG_VERBOSE)
268         CLog::Log(LOGDEBUG, ">>> new format col:%d, w:%d, h:%d, sw:%d, sh:%d, ctl:%d,%d; cbr:%d,%d\n", p->videoColorFormat, p->width, p->height, p->videoStride, p->videoSliceHeight, cropTop, cropLeft, cropBottom, cropRight);
269 #endif
270
271         if (frame->medbuf)
272           frame->medbuf->release();
273         frame->medbuf = NULL;
274         free(frame);
275         continue;
276       }
277       else
278       {
279         CLog::Log(LOGERROR, "%s - decoding error (%d)\n", CLASSNAME,frame->status);
280         if (frame->medbuf)
281           frame->medbuf->release();
282         frame->medbuf = NULL;
283         free(frame);
284         continue;
285       }
286
287       if (frame->format == RENDER_FMT_EGLIMG)
288       {
289         if (!p->eglInitialized)
290         {
291           p->InitializeEGL(frame->width, frame->height);
292         }
293         else if (p->texwidth != frame->width || p->texheight != frame->height)
294         {
295           p->ReleaseEGL();
296           p->InitializeEGL(frame->width, frame->height);
297         }
298
299         ANativeWindowBuffer* graphicBuffer = frame->medbuf->graphicBuffer()->getNativeBuffer();
300         native_window_set_buffers_timestamp(p->mVideoNativeWindow.get(), frame->pts * 1000);
301         int err = p->mVideoNativeWindow.get()->queueBuffer(p->mVideoNativeWindow.get(), graphicBuffer);
302         if (err == 0)
303           frame->medbuf->meta_data()->setInt32(kKeyRendered, 1);
304         frame->medbuf->release();
305         frame->medbuf = NULL;
306         p->UpdateSurfaceTexture();
307
308         if (!p->drop_state)
309         {
310           p->free_mutex.lock();
311
312           stSlot* cur_slot = p->getFreeSlot();
313           if (!cur_slot)
314           {
315             CLog::Log(LOGERROR, "STF: No free output buffers\n");
316             continue;
317           }
318
319           p->fbo.BindToTexture(GL_TEXTURE_2D, cur_slot->texid);
320           p->fbo.BeginRender();
321
322           glDisable(GL_DEPTH_TEST);
323           //glClear(GL_COLOR_BUFFER_BIT);
324
325           const GLfloat triangleVertices[] = {
326           -1.0f, 1.0f,
327           -1.0f, -1.0f,
328           1.0f, -1.0f,
329           1.0f, 1.0f,
330           };
331
332           glVertexAttribPointer(p->mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);
333           glEnableVertexAttribArray(p->mPositionHandle);
334
335           glUseProgram(p->mPgm);
336           glUniform1i(p->mTexSamplerHandle, 0);
337
338           glBindTexture(GL_TEXTURE_EXTERNAL_OES, p->mVideoTextureId);
339
340           GLfloat texMatrix[16];
341           p->GetSurfaceTextureTransformMatrix(texMatrix);
342           glUniformMatrix4fv(p->mTexMatrixHandle, 1, GL_FALSE, texMatrix);
343
344           glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
345
346           glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
347           p->fbo.EndRender();
348
349           glBindTexture(GL_TEXTURE_2D, 0);
350
351           frame->eglimg = cur_slot->eglimg;
352           p->free_mutex.unlock();
353         }
354       }
355
356     #if defined(DEBUG_VERBOSE)
357       CLog::Log(LOGDEBUG, "%s: >>> pushed OUT frame; w:%d, h:%d, img:%p, tm:%d\n", CLASSNAME, frame->width, frame->height, frame->eglimg, XbmcThreads::SystemClockMillis() - time);
358     #endif
359
360       p->out_mutex.lock();
361       p->cur_frame = frame;
362       while (p->cur_frame)
363         p->out_condition.wait(p->out_mutex);
364       p->out_mutex.unlock();
365     }
366     while (!decode_done && !m_bStop);
367
368     if (p->eglInitialized)
369       p->ReleaseEGL();
370
371   }
372 };
373
374 /***********************************************************/
375
376 CStageFrightVideo::CStageFrightVideo(CApplication* application, CApplicationMessenger* applicationMessenger, CWinSystemEGL* windowing, CAdvancedSettings* advsettings)
377 {
378 #if defined(DEBUG_VERBOSE)
379   CLog::Log(LOGDEBUG, "%s::ctor: %d\n", CLASSNAME, sizeof(CStageFrightVideo));
380 #endif
381   p = new CStageFrightVideoPrivate;
382   p->m_g_application = application;
383   p->m_g_applicationMessenger = applicationMessenger;
384   p->m_g_Windowing = windowing;
385   p->m_g_advancedSettings = advsettings;
386 }
387
388 CStageFrightVideo::~CStageFrightVideo()
389 {
390   delete p;
391 }
392
393 bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
394 {
395 #if defined(DEBUG_VERBOSE)
396   CLog::Log(LOGDEBUG, "%s::Open\n", CLASSNAME);
397 #endif
398
399   CSingleLock lock(g_graphicsContext);
400
401   // stagefright crashes with null size. Trap this...
402   if (!hints.width || !hints.height)
403   {
404     CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"null size, cannot handle");
405     return false;
406   }
407   p->width     = hints.width;
408   p->height    = hints.height;
409
410   if (p->m_g_advancedSettings->m_stagefrightConfig.useSwRenderer)
411     p->quirks |= QuirkSWRender;
412
413   p->meta = new MetaData;
414   if (p->meta == NULL)
415   {
416     CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"cannot allocate MetaData");
417     return false;
418   }
419
420   const char* mimetype;
421   switch (hints.codec)
422   {
423   case CODEC_ID_H264:
424     if (p->m_g_advancedSettings->m_stagefrightConfig.useAVCcodec == 0)
425       return false;
426     mimetype = "video/avc";
427     if ( *(char*)hints.extradata == 1 )
428       p->meta->setData(kKeyAVCC, kTypeAVCC, hints.extradata, hints.extrasize);
429     break;
430   case CODEC_ID_MPEG4:
431     if (p->m_g_advancedSettings->m_stagefrightConfig.useMP4codec == 0)
432       return false;
433     mimetype = "video/mp4v-es";
434     break;
435   case CODEC_ID_MPEG2VIDEO:
436     if (p->m_g_advancedSettings->m_stagefrightConfig.useMPEG2codec == 0)
437       return false;
438     mimetype = "video/mpeg2";
439     break;
440   case CODEC_ID_VP3:
441   case CODEC_ID_VP6:
442   case CODEC_ID_VP6F:
443       if (p->m_g_advancedSettings->m_stagefrightConfig.useVPXcodec == 0)
444         return false;
445       mimetype = "video/vp6";
446       break;
447   case CODEC_ID_VP8:
448     if (p->m_g_advancedSettings->m_stagefrightConfig.useVPXcodec == 0)
449       return false;
450     mimetype = "video/x-vnd.on2.vp8";
451     break;
452   case CODEC_ID_VC1:
453   case CODEC_ID_WMV3:
454     if (p->m_g_advancedSettings->m_stagefrightConfig.useVC1codec == 0)
455       return false;
456     mimetype = "video/vc1";
457     break;
458   default:
459     return false;
460     break;
461   }
462
463   p->meta->setCString(kKeyMIMEType, mimetype);
464   p->meta->setInt32(kKeyWidth, p->width);
465   p->meta->setInt32(kKeyHeight, p->height);
466
467   android::ProcessState::self()->startThreadPool();
468
469   p->source    = new CStageFrightMediaSource(p, p->meta);
470   p->client    = new OMXClient;
471
472   if (p->source == NULL || p->client == NULL)
473   {
474     p->meta = NULL;
475     p->source = NULL;
476     p->decoder = NULL;
477     CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot obtain source / client");
478     return false;
479   }
480
481   if (p->client->connect() !=  OK)
482   {
483     p->meta = NULL;
484     p->source = NULL;
485     delete p->client;
486     p->client = NULL;
487     CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot connect OMX client");
488     return false;
489   }
490
491   if ((p->quirks & QuirkSWRender) == 0)
492     if (!p->InitSurfaceTexture())
493     {
494       p->meta = NULL;
495       p->source = NULL;
496       delete p->client;
497       p->client = NULL;
498       CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot allocate texture");
499       return false;
500     }
501
502   p->decoder  = OMXCodec::Create(p->client->interface(), p->meta,
503                                          false, p->source, NULL,
504                                          OMXCodec::kHardwareCodecsOnly | (p->quirks & QuirkSWRender ? OMXCodec::kClientNeedsFramebuffer : 0),
505                                          p->mVideoNativeWindow
506                                          );
507
508   if (!(p->decoder != NULL && p->decoder->start() ==  OK))
509   {
510     p->meta = NULL;
511     p->source = NULL;
512     p->decoder = NULL;
513     return false;
514   }
515
516   sp<MetaData> outFormat = p->decoder->getFormat();
517
518   if (!outFormat->findInt32(kKeyWidth, &p->width) || !outFormat->findInt32(kKeyHeight, &p->height)
519         || !outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat))
520   {
521     p->meta = NULL;
522     p->source = NULL;
523     p->decoder = NULL;
524     return false;
525   }
526
527   const char *component;
528   if (outFormat->findCString(kKeyDecoderComponent, &component))
529   {
530     CLog::Log(LOGDEBUG, "%s::%s - component: %s\n", CLASSNAME, __func__, component);
531
532     //Blacklist
533     if (!strncmp(component, "OMX.google", 10))
534     {
535       // On some platforms, software decoders are returned anyway
536       CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (software)");
537       return false;
538     }
539     else if (!strncmp(component, "OMX.Nvidia.mp4.decode", 21) && p->m_g_advancedSettings->m_stagefrightConfig.useMP4codec != 1)
540     {
541       // Has issues with some XVID encoded MP4. Only fails after actual decoding starts...
542       CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (MP4)");
543       return false;
544     }
545   }
546
547   int32_t cropLeft, cropTop, cropRight, cropBottom;
548   cropLeft = cropTop = cropRight = cropBottom = 0;
549   if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
550   {
551     p->x = 0;
552     p->y = 0;
553   }
554   else
555   {
556     p->x = cropLeft;
557     p->y = cropTop;
558     p->width = cropRight - cropLeft + 1;
559     p->height = cropBottom - cropTop + 1;
560   }
561
562   if (!outFormat->findInt32(kKeyStride, &p->videoStride))
563     p->videoStride = p->width;
564   if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
565     p->videoSliceHeight = p->height;
566
567   for (int i=0; i<INBUFCOUNT; ++i)
568   {
569     p->inbuf[i] = new MediaBuffer(300000);
570     p->inbuf[i]->setObserver(p);
571   }
572
573   p->decode_thread = new CStageFrightDecodeThread(p);
574   p->decode_thread->Create(true /*autodelete*/);
575
576 #if defined(DEBUG_VERBOSE)
577   CLog::Log(LOGDEBUG, ">>> format col:%d, w:%d, h:%d, sw:%d, sh:%d, ctl:%d,%d; cbr:%d,%d\n", p->videoColorFormat, p->width, p->height, p->videoStride, p->videoSliceHeight, cropTop, cropLeft, cropBottom, cropRight);
578 #endif
579
580   return true;
581 }
582
583 /*** Decode ***/
584 int  CStageFrightVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
585 {
586 #if defined(DEBUG_VERBOSE)
587   unsigned int time = XbmcThreads::SystemClockMillis();
588   CLog::Log(LOGDEBUG, "%s::Decode - d:%p; s:%d; dts:%f; pts:%f\n", CLASSNAME, pData, iSize, dts, pts);
589 #endif
590
591   Frame *frame;
592   int demuxer_bytes = iSize;
593   uint8_t *demuxer_content = pData;
594   int ret = 0;
595
596   if (demuxer_content)
597   {
598     frame = (Frame*)malloc(sizeof(Frame));
599     if (!frame)
600       return VC_ERROR;
601
602     frame->status  = OK;
603     if (p->m_g_advancedSettings->m_stagefrightConfig.useInputDTS)
604       frame->pts = (dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : ((pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : 0);
605     else
606       frame->pts = (pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : ((dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : 0);
607
608     // No valid pts? libstagefright asserts on this.
609     if (frame->pts < 0)
610     {
611       free(frame);
612       return ret;
613     }
614
615     frame->medbuf = p->getBuffer(demuxer_bytes);
616     if (!frame->medbuf)
617     {
618       CLog::Log(LOGWARNING, "STF: Cannot get input buffer\n");
619       free(frame);
620       return VC_ERROR;
621     }
622
623     fast_memcpy(frame->medbuf->data(), demuxer_content, demuxer_bytes);
624     frame->medbuf->meta_data()->clear();
625     frame->medbuf->meta_data()->setInt64(kKeyTime, frame->pts);
626
627     p->in_mutex.lock();
628     p->in_queue.push_back(frame);
629     p->in_condition.notify();
630     p->in_mutex.unlock();
631   }
632
633   if (p->inputBufferAvailable() && p->in_queue.size() < INBUFCOUNT)
634     ret |= VC_BUFFER;
635   else
636     usleep(1000);
637   if (p->cur_frame != NULL)
638     ret |= VC_PICTURE;
639 #if defined(DEBUG_VERBOSE)
640   CLog::Log(LOGDEBUG, "%s::Decode: pushed IN frame (%d); tm:%d\n", CLASSNAME,p->in_queue.size(), XbmcThreads::SystemClockMillis() - time);
641 #endif
642
643   return ret;
644 }
645
646 bool CStageFrightVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
647 {
648  #if defined(DEBUG_VERBOSE)
649   unsigned int time = XbmcThreads::SystemClockMillis();
650 #endif
651   if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG && pDvdVideoPicture->eglimg != EGL_NO_IMAGE_KHR)
652     ReleaseBuffer(pDvdVideoPicture->eglimg);
653
654   if (p->prev_frame) {
655     if (p->prev_frame->medbuf)
656       p->prev_frame->medbuf->release();
657     free(p->prev_frame);
658     p->prev_frame = NULL;
659   }
660 #if defined(DEBUG_VERBOSE)
661   CLog::Log(LOGDEBUG, "%s::ClearPicture (%d)\n", CLASSNAME, XbmcThreads::SystemClockMillis() - time);
662 #endif
663
664   return true;
665 }
666
667 bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
668 {
669 #if defined(DEBUG_VERBOSE)
670   unsigned int time = XbmcThreads::SystemClockMillis();
671   CLog::Log(LOGDEBUG, "%s::GetPicture\n", CLASSNAME);
672   if (p->cycle_time != 0)
673     CLog::Log(LOGDEBUG, ">>> cycle dur:%d\n", XbmcThreads::SystemClockMillis() - p->cycle_time);
674   p->cycle_time = time;
675 #endif
676
677   status_t status;
678
679   p->out_mutex.lock();
680   if (!p->cur_frame)
681   {
682     CLog::Log(LOGERROR, "%s::%s - Error getting frame\n", CLASSNAME, __func__);
683     p->out_condition.notify();
684     p->out_mutex.unlock();
685     return false;
686   }
687
688   Frame *frame = p->cur_frame;
689   status  = frame->status;
690
691   pDvdVideoPicture->format = frame->format;
692   pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
693   pDvdVideoPicture->pts = frame->pts;
694   pDvdVideoPicture->iWidth  = frame->width;
695   pDvdVideoPicture->iHeight = frame->height;
696   pDvdVideoPicture->iDisplayWidth = frame->width;
697   pDvdVideoPicture->iDisplayHeight = frame->height;
698   pDvdVideoPicture->iFlags  = DVP_FLAG_ALLOCATED;
699   pDvdVideoPicture->eglimg = EGL_NO_IMAGE_KHR;
700
701   if (status != OK)
702   {
703     CLog::Log(LOGERROR, "%s::%s - Error getting picture from frame(%d)\n", CLASSNAME, __func__,status);
704     if (frame->medbuf) {
705       frame->medbuf->release();
706     }
707     free(frame);
708     p->cur_frame = NULL;
709     p->out_condition.notify();
710     p->out_mutex.unlock();
711     return false;
712   }
713
714   if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG)
715   {
716     pDvdVideoPicture->eglimg = frame->eglimg;
717     if (pDvdVideoPicture->eglimg == EGL_NO_IMAGE_KHR)
718       pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
719     else
720       LockBuffer(pDvdVideoPicture->eglimg);
721   #if defined(DEBUG_VERBOSE)
722     CLog::Log(LOGDEBUG, ">>> pic dts:%f, pts:%llu, img:%p, tm:%d\n", pDvdVideoPicture->dts, frame->pts, pDvdVideoPicture->eglimg, XbmcThreads::SystemClockMillis() - time);
723   #endif
724   }
725   else if (pDvdVideoPicture->format == RENDER_FMT_YUV420P)
726   {
727     pDvdVideoPicture->color_range  = 0;
728     pDvdVideoPicture->color_matrix = 4;
729
730     unsigned int luma_pixels = frame->width  * frame->height;
731     unsigned int chroma_pixels = luma_pixels/4;
732     uint8_t* data = NULL;
733     if (frame->medbuf && !p->drop_state)
734     {
735       data = (uint8_t*)((long)frame->medbuf->data() + frame->medbuf->range_offset());
736     }
737     switch (p->videoColorFormat)
738     {
739       case OMX_COLOR_FormatYUV420Planar:
740         pDvdVideoPicture->iLineSize[0] = frame->width;
741         pDvdVideoPicture->iLineSize[1] = frame->width / 2;
742         pDvdVideoPicture->iLineSize[2] = frame->width / 2;
743         pDvdVideoPicture->iLineSize[3] = 0;
744         pDvdVideoPicture->data[0] = data;
745         pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
746         pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
747         pDvdVideoPicture->data[3] = 0;
748         break;
749       case OMX_COLOR_FormatYUV420SemiPlanar:
750       case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
751       case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
752         pDvdVideoPicture->iLineSize[0] = frame->width;
753         pDvdVideoPicture->iLineSize[1] = frame->width;
754         pDvdVideoPicture->iLineSize[2] = 0;
755         pDvdVideoPicture->iLineSize[3] = 0;
756         pDvdVideoPicture->data[0] = data;
757         pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
758         pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
759         pDvdVideoPicture->data[3] = 0;
760         break;
761       default:
762         CLog::Log(LOGERROR, "%s::%s - Unsupported color format(%d)\n", CLASSNAME, __func__,p->videoColorFormat);
763     }
764   #if defined(DEBUG_VERBOSE)
765     CLog::Log(LOGDEBUG, ">>> pic pts:%f, data:%p, col:%d, w:%d, h:%d, tm:%d\n", pDvdVideoPicture->pts, data, p->videoColorFormat, frame->width, frame->height, XbmcThreads::SystemClockMillis() - time);
766   #endif
767   }
768
769   if (p->drop_state)
770     pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
771
772   p->prev_frame = p->cur_frame;
773   p->cur_frame = NULL;
774   p->out_condition.notify();
775   p->out_mutex.unlock();
776
777   return true;
778 }
779
780 void CStageFrightVideo::Dispose()
781 {
782 #if defined(DEBUG_VERBOSE)
783   CLog::Log(LOGDEBUG, "%s::Close\n", CLASSNAME);
784 #endif
785
786   Frame *frame;
787
788   if (p->decode_thread && p->decode_thread->IsRunning())
789     p->decode_thread->StopThread(false);
790   p->decode_thread = NULL;
791   p->in_condition.notify();
792
793   // Give decoder_thread time to process EOS, if stuck on reading
794   usleep(50000);
795
796 #if defined(DEBUG_VERBOSE)
797   CLog::Log(LOGDEBUG, "Cleaning OUT\n");
798 #endif
799   p->out_mutex.lock();
800   if (p->cur_frame)
801   {
802     if (p->cur_frame->medbuf)
803       p->cur_frame->medbuf->release();
804     free(p->cur_frame);
805     p->cur_frame = NULL;
806   }
807   p->out_condition.notify();
808   p->out_mutex.unlock();
809
810   if (p->prev_frame)
811   {
812     if (p->prev_frame->medbuf)
813       p->prev_frame->medbuf->release();
814     free(p->prev_frame);
815     p->prev_frame = NULL;
816   }
817
818 #if defined(DEBUG_VERBOSE)
819   CLog::Log(LOGDEBUG, "Stopping omxcodec\n");
820 #endif
821   if (p->decoder != NULL)
822   {
823     p->decoder->stop();
824     p->decoder = NULL;
825   }
826   if (p->client)
827   {
828     p->client->disconnect();
829     delete p->client;
830   }
831   p->meta = NULL;
832
833 #if defined(DEBUG_VERBOSE)
834   CLog::Log(LOGDEBUG, "Cleaning IN(%d)\n", p->in_queue.size());
835 #endif
836   std::list<Frame*>::iterator it;
837   while (!p->in_queue.empty())
838   {
839     it = p->in_queue.begin();
840     frame = *it;
841     p->in_queue.erase(it);
842     if (frame->medbuf)
843       frame->medbuf->release();
844     free(frame);
845   }
846   for (int i=0; i<INBUFCOUNT; ++i)
847   {
848     if (p->inbuf[i])
849     {
850       p->inbuf[i]->setObserver(NULL);
851       p->inbuf[i]->release();
852       p->inbuf[i] = NULL;
853     }
854   }
855   p->source = NULL;
856
857 #if defined(DEBUG_VERBOSE)
858   CLog::Log(LOGDEBUG, "Cleaning libstagefright\n", p->in_queue.size());
859 #endif
860   if ((p->quirks & QuirkSWRender) == 0)
861     p->ReleaseSurfaceTexture();
862
863 #if defined(DEBUG_VERBOSE)
864   CLog::Log(LOGDEBUG, "Final Cleaning\n", p->in_queue.size());
865 #endif
866   if (p->decoder_component)
867     free(&p->decoder_component);
868 }
869
870 void CStageFrightVideo::Reset(void)
871 {
872 #if defined(DEBUG_VERBOSE)
873   CLog::Log(LOGDEBUG, "%s::Reset\n", CLASSNAME);
874 #endif
875   Frame* frame;
876   p->in_mutex.lock();
877   std::list<Frame*>::iterator it;
878   while (!p->in_queue.empty())
879   {
880     it = p->in_queue.begin();
881     frame = *it;
882     p->in_queue.erase(it);
883     if (frame->medbuf)
884       frame->medbuf->release();
885     free(frame);
886   }
887   p->resetting = true;
888
889   p->in_mutex.unlock();
890 }
891
892 void CStageFrightVideo::SetDropState(bool bDrop)
893 {
894   if (bDrop == p->drop_state)
895     return;
896
897 #if defined(DEBUG_VERBOSE)
898   CLog::Log(LOGDEBUG, "%s::SetDropState (%d->%d)\n", CLASSNAME,p->drop_state,bDrop);
899 #endif
900
901   p->drop_state = bDrop;
902 }
903
904 void CStageFrightVideo::SetSpeed(int iSpeed)
905 {
906 }
907
908 /***************/
909
910 void CStageFrightVideo::LockBuffer(EGLImageKHR eglimg)
911 {
912 #if defined(DEBUG_VERBOSE)
913   unsigned int time = XbmcThreads::SystemClockMillis();
914 #endif
915   p->free_mutex.lock();
916   stSlot* slot = p->getSlot(eglimg);
917   if (!slot)
918   {
919     CLog::Log(LOGDEBUG, "STF: LockBuffer: Unknown img(%p)", eglimg);
920     p->free_mutex.unlock();
921     return;
922   }
923   slot->use_cnt++;
924
925 #if defined(DEBUG_VERBOSE)
926   CLog::Log(LOGDEBUG, "STF: LockBuffer: Locking %p: cnt:%d tm:%d\n", eglimg, slot->use_cnt, XbmcThreads::SystemClockMillis() - time);
927 #endif
928   p->free_mutex.unlock();
929 }
930
931 void CStageFrightVideo::ReleaseBuffer(EGLImageKHR eglimg)
932 {
933 #if defined(DEBUG_VERBOSE)
934   unsigned int time = XbmcThreads::SystemClockMillis();
935 #endif
936   p->free_mutex.lock();
937   stSlot* slot = p->getSlot(eglimg);
938   if (!slot)
939   {
940     CLog::Log(LOGDEBUG, "STF: ReleaseBuffer: Unknown img(%p)", eglimg);
941     p->free_mutex.unlock();
942     return;
943   }
944   if (slot->use_cnt == 0)
945   {
946     CLog::Log(LOGDEBUG, "STF: ReleaseBuffer: already unlocked img(%p)", eglimg);
947     p->free_mutex.unlock();
948     return;
949   }
950   slot->use_cnt--;
951
952 #if defined(DEBUG_VERBOSE)
953   CLog::Log(LOGDEBUG, "STF: ReleaseBuffer: Unlocking %p: cnt:%d tm:%d\n", eglimg, slot->use_cnt, XbmcThreads::SystemClockMillis() - time);
954 #endif
955   p->free_mutex.unlock();
956 }