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