[Confluence] align subtitle popup to the bottom
[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   }
545
546   cropLeft = cropTop = cropRight = cropBottom = 0;
547   if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
548   {
549     p->x = 0;
550     p->y = 0;
551   }
552   else
553   {
554     p->x = cropLeft;
555     p->y = cropTop;
556     p->width = cropRight - cropLeft + 1;
557     p->height = cropBottom - cropTop + 1;
558   }
559
560   if (!outFormat->findInt32(kKeyStride, &p->videoStride))
561     p->videoStride = p->width;
562   if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
563     p->videoSliceHeight = p->height;
564
565   for (int i=0; i<INBUFCOUNT; ++i)
566   {
567     p->inbuf[i] = new MediaBuffer(300000);
568     p->inbuf[i]->setObserver(p);
569   }
570
571   p->decode_thread = new CStageFrightDecodeThread(p);
572   p->decode_thread->Create(true /*autodelete*/);
573
574 #if defined(DEBUG_VERBOSE)
575   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);
576 #endif
577
578   return true;
579
580 fail:
581   if (p->decoder != 0)
582     p->decoder->stop();
583   if (p->client)
584   {
585     p->client->disconnect();
586     delete p->client;
587   }
588   if (p->decoder_component)
589     free(&p->decoder_component);
590   if ((p->quirks & QuirkSWRender) == 0)
591     p->UninitStagefrightSurface();
592   return false;
593 }
594
595 /*** Decode ***/
596 int  CStageFrightVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
597 {
598 #if defined(DEBUG_VERBOSE)
599   unsigned int time = XbmcThreads::SystemClockMillis();
600   CLog::Log(LOGDEBUG, "%s::Decode - d:%p; s:%d; dts:%f; pts:%f\n", CLASSNAME, pData, iSize, dts, pts);
601 #endif
602
603   Frame *frame;
604   int demuxer_bytes = iSize;
605   uint8_t *demuxer_content = pData;
606   int ret = 0;
607
608   if (demuxer_content)
609   {
610     frame = (Frame*)malloc(sizeof(Frame));
611     if (!frame)
612       return VC_ERROR;
613
614     frame->status  = OK;
615     if (g_advancedSettings.m_stagefrightConfig.useInputDTS)
616       frame->pts = (dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : ((pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : 0);
617     else
618       frame->pts = (pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : ((dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : 0);
619
620     // No valid pts? libstagefright asserts on this.
621     if (frame->pts < 0)
622     {
623       free(frame);
624       return ret;
625     }
626
627     frame->medbuf = p->getBuffer(demuxer_bytes);
628     if (!frame->medbuf)
629     {
630       free(frame);
631       return VC_ERROR;
632     }
633
634     fast_memcpy(frame->medbuf->data(), demuxer_content, demuxer_bytes);
635     frame->medbuf->meta_data()->clear();
636     frame->medbuf->meta_data()->setInt64(kKeyTime, frame->pts);
637
638     p->in_mutex.lock();
639     p->framecount++;
640     p->in_queue.insert(std::pair<int64_t, Frame*>(p->framecount, frame));
641     p->in_condition.notify();
642     p->in_mutex.unlock();
643   }
644
645   if (p->inputBufferAvailable() && p->in_queue.size() < INBUFCOUNT)
646     ret |= VC_BUFFER;
647   else
648     usleep(1000);
649   if (p->cur_frame != NULL)
650     ret |= VC_PICTURE;
651 #if defined(DEBUG_VERBOSE)
652   CLog::Log(LOGDEBUG, "%s::Decode: pushed IN frame (%d); tm:%d\n", CLASSNAME,p->in_queue.size(), XbmcThreads::SystemClockMillis() - time);
653 #endif
654
655   return ret;
656 }
657
658 bool CStageFrightVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
659 {
660  #if defined(DEBUG_VERBOSE)
661   unsigned int time = XbmcThreads::SystemClockMillis();
662 #endif
663   if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG && pDvdVideoPicture->eglimg != EGL_NO_IMAGE_KHR)
664     ReleaseBuffer(pDvdVideoPicture->eglimg);
665
666   if (p->prev_frame) {
667     if (p->prev_frame->medbuf)
668       p->prev_frame->medbuf->release();
669     free(p->prev_frame);
670     p->prev_frame = NULL;
671   }
672 #if defined(DEBUG_VERBOSE)
673   CLog::Log(LOGDEBUG, "%s::ClearPicture (%d)\n", CLASSNAME, XbmcThreads::SystemClockMillis() - time);
674 #endif
675
676   return true;
677 }
678
679 bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
680 {
681 #if defined(DEBUG_VERBOSE)
682   unsigned int time = XbmcThreads::SystemClockMillis();
683   CLog::Log(LOGDEBUG, "%s::GetPicture\n", CLASSNAME);
684   if (p->cycle_time != 0)
685     CLog::Log(LOGDEBUG, ">>> cycle dur:%d\n", XbmcThreads::SystemClockMillis() - p->cycle_time);
686   p->cycle_time = time;
687 #endif
688
689   status_t status;
690
691   p->out_mutex.lock();
692   if (!p->cur_frame)
693   {
694     CLog::Log(LOGERROR, "%s::%s - Error getting frame\n", CLASSNAME, __func__);
695     p->out_condition.notify();
696     p->out_mutex.unlock();
697     return false;
698   }
699
700   Frame *frame = p->cur_frame;
701   status  = frame->status;
702
703   pDvdVideoPicture->format = frame->format;
704   pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
705   pDvdVideoPicture->pts = frame->pts;
706   pDvdVideoPicture->iWidth  = frame->width;
707   pDvdVideoPicture->iHeight = frame->height;
708   pDvdVideoPicture->iDisplayWidth = frame->width;
709   pDvdVideoPicture->iDisplayHeight = frame->height;
710   pDvdVideoPicture->iFlags  = DVP_FLAG_ALLOCATED;
711   pDvdVideoPicture->stf = this;
712   pDvdVideoPicture->eglimg = EGL_NO_IMAGE_KHR;
713
714   if (status != OK)
715   {
716     CLog::Log(LOGERROR, "%s::%s - Error getting picture from frame(%d)\n", CLASSNAME, __func__,status);
717     if (frame->medbuf) {
718       frame->medbuf->release();
719     }
720     free(frame);
721     p->cur_frame = NULL;
722     p->out_condition.notify();
723     p->out_mutex.unlock();
724     return false;
725   }
726
727   if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG)
728   {
729     pDvdVideoPicture->eglimg = frame->eglimg;
730   #if defined(DEBUG_VERBOSE)
731     CLog::Log(LOGDEBUG, ">>> pic dts:%f, pts:%llu, img:%p, tm:%d\n", pDvdVideoPicture->dts, frame->pts, pDvdVideoPicture->eglimg, XbmcThreads::SystemClockMillis() - time);
732   #endif
733   }
734   else if (pDvdVideoPicture->format == RENDER_FMT_YUV420P)
735   {
736     pDvdVideoPicture->color_range  = 0;
737     pDvdVideoPicture->color_matrix = 4;
738
739     unsigned int luma_pixels = frame->width  * frame->height;
740     unsigned int chroma_pixels = luma_pixels/4;
741     uint8_t* data = NULL;
742     if (frame->medbuf && !p->drop_state)
743     {
744       data = (uint8_t*)((long)frame->medbuf->data() + frame->medbuf->range_offset());
745     }
746     switch (p->videoColorFormat)
747     {
748       case OMX_COLOR_FormatYUV420Planar:
749         pDvdVideoPicture->iLineSize[0] = frame->width;
750         pDvdVideoPicture->iLineSize[1] = frame->width / 2;
751         pDvdVideoPicture->iLineSize[2] = frame->width / 2;
752         pDvdVideoPicture->iLineSize[3] = 0;
753         pDvdVideoPicture->data[0] = data;
754         pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
755         pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
756         pDvdVideoPicture->data[3] = 0;
757         break;
758       case OMX_COLOR_FormatYUV420SemiPlanar:
759       case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
760       case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
761         pDvdVideoPicture->iLineSize[0] = frame->width;
762         pDvdVideoPicture->iLineSize[1] = frame->width;
763         pDvdVideoPicture->iLineSize[2] = 0;
764         pDvdVideoPicture->iLineSize[3] = 0;
765         pDvdVideoPicture->data[0] = data;
766         pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
767         pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
768         pDvdVideoPicture->data[3] = 0;
769         break;
770       default:
771         CLog::Log(LOGERROR, "%s::%s - Unsupported color format(%d)\n", CLASSNAME, __func__,p->videoColorFormat);
772     }
773   #if defined(DEBUG_VERBOSE)
774     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);
775   #endif
776   }
777
778   if (p->drop_state)
779     pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
780
781   p->prev_frame = p->cur_frame;
782   p->cur_frame = NULL;
783   p->out_condition.notify();
784   p->out_mutex.unlock();
785
786   return true;
787 }
788
789 void CStageFrightVideo::Close()
790 {
791 #if defined(DEBUG_VERBOSE)
792   CLog::Log(LOGDEBUG, "%s::Close\n", CLASSNAME);
793 #endif
794
795   Frame *frame;
796
797   if (p->decode_thread && p->decode_thread->IsRunning())
798     p->decode_thread->StopThread(false);
799   p->decode_thread = NULL;
800   p->in_condition.notify();
801
802   // Give decoder_thread time to process EOS, if stuck on reading
803   usleep(50000);
804
805 #if defined(DEBUG_VERBOSE)
806   CLog::Log(LOGDEBUG, "Cleaning OUT\n");
807 #endif
808   p->out_mutex.lock();
809   if (p->cur_frame)
810   {
811     if (p->cur_frame->medbuf)
812       p->cur_frame->medbuf->release();
813     free(p->cur_frame);
814     p->cur_frame = NULL;
815   }
816   p->out_condition.notify();
817   p->out_mutex.unlock();
818
819   if (p->prev_frame)
820   {
821     if (p->prev_frame->medbuf)
822       p->prev_frame->medbuf->release();
823     free(p->prev_frame);
824     p->prev_frame = NULL;
825   }
826
827 #if defined(DEBUG_VERBOSE)
828   CLog::Log(LOGDEBUG, "Stopping omxcodec\n");
829 #endif
830   p->decoder->stop();
831   p->client->disconnect();
832
833 #if defined(DEBUG_VERBOSE)
834   CLog::Log(LOGDEBUG, "Cleaning IN(%d)\n", p->in_queue.size());
835 #endif
836   std::map<int64_t,Frame*>::iterator it;
837   while (!p->in_queue.empty())
838   {
839     it = p->in_queue.begin();
840     frame = it->second;
841     p->in_queue.erase(it);
842     if (frame->medbuf)
843       frame->medbuf->release();
844     free(frame);
845   }
846
847   if (p->decoder_component)
848     free(&p->decoder_component);
849
850   delete p->client;
851
852   if ((p->quirks & QuirkSWRender) == 0)
853     p->UninitStagefrightSurface();
854
855   for (int i=0; i<INBUFCOUNT; ++i)
856   {
857     p->inbuf[i]->setObserver(NULL);
858     p->inbuf[i]->release();
859   }
860
861   delete p;
862 }
863
864 void CStageFrightVideo::Reset(void)
865 {
866 #if defined(DEBUG_VERBOSE)
867   CLog::Log(LOGDEBUG, "%s::Reset\n", CLASSNAME);
868 #endif
869   Frame* frame;
870   p->in_mutex.lock();
871   std::map<int64_t,Frame*>::iterator it;
872   while (!p->in_queue.empty())
873   {
874     it = p->in_queue.begin();
875     frame = it->second;
876     p->in_queue.erase(it);
877     if (frame->medbuf)
878       frame->medbuf->release();
879     free(frame);
880   }
881   p->resetting = true;
882   p->framecount = 0;
883
884   p->in_mutex.unlock();
885 }
886
887 void CStageFrightVideo::SetDropState(bool bDrop)
888 {
889   if (bDrop == p->drop_state)
890     return;
891
892 #if defined(DEBUG_VERBOSE)
893   CLog::Log(LOGDEBUG, "%s::SetDropState (%d->%d)\n", CLASSNAME,p->drop_state,bDrop);
894 #endif
895
896   p->drop_state = bDrop;
897 }
898
899 void CStageFrightVideo::SetSpeed(int iSpeed)
900 {
901 }
902
903 /***************/
904
905 void CStageFrightVideo::LockBuffer(EGLImageKHR eglimg)
906 {
907  #if defined(DEBUG_VERBOSE)
908   unsigned int time = XbmcThreads::SystemClockMillis();
909 #endif
910   p->free_mutex.lock();
911   std::list<std::pair<EGLImageKHR, int> >::iterator it = p->free_queue.begin();
912   for(;it != p->free_queue.end(); ++it)
913   {
914     if ((*it).first == eglimg)
915       break;
916   }
917   if (it == p->free_queue.end())
918   {
919     p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
920     p->free_mutex.unlock();
921     return;
922   }
923 #if defined(DEBUG_VERBOSE)
924   CLog::Log(LOGDEBUG, "Locking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
925 #endif
926
927   p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
928   p->free_queue.erase(it);
929   p->free_mutex.unlock();
930 }
931
932 void CStageFrightVideo::ReleaseBuffer(EGLImageKHR eglimg)
933 {
934  #if defined(DEBUG_VERBOSE)
935   unsigned int time = XbmcThreads::SystemClockMillis();
936 #endif
937   p->free_mutex.lock();
938   int cnt = 0;
939   std::list<std::pair<EGLImageKHR, int> >::iterator it = p->busy_queue.begin();
940   std::list<std::pair<EGLImageKHR, int> >::iterator itfree;
941   for(;it != p->busy_queue.end(); ++it)
942   {
943     if ((*it).first == eglimg)
944     {
945       cnt++;
946       if (cnt==1)
947         itfree = it;
948       else
949         break;
950     }
951   }
952   if (it == p->busy_queue.end() && !cnt)
953   {
954     p->free_mutex.unlock();
955     return;
956   }
957 #if defined(DEBUG_VERBOSE)
958   CLog::Log(LOGDEBUG, "Unlocking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
959 #endif
960
961   if (cnt==1)
962   {
963     p->free_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
964     p->busy_queue.erase(itfree);
965   }
966   p->free_mutex.unlock();
967 }