Merge pull request #2969 from fritsch/ae-fix-wrong-softresume
[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         decode_done   = 1;
302         if (frame->medbuf)
303           frame->medbuf->release();
304         frame->medbuf = NULL;
305       }
306
307       if (frame->format == RENDER_FMT_EGLIMG)
308       {
309         if (!p->eglInitialized)
310         {
311           p->InitializeEGL(frame->width, frame->height);
312         } 
313         else if (p->texwidth != frame->width || p->texheight != frame->height)
314         {
315           p->UninitializeEGL();
316           p->InitializeEGL(frame->width, frame->height);
317         }
318
319         if (p->free_queue.empty())
320         {
321           CLog::Log(LOGERROR, "%s::%s - Error: No free output buffers\n", CLASSNAME, __func__);
322           if (frame->medbuf) 
323             frame->medbuf->release();
324           free(frame);
325           continue;
326         }  
327
328         ANativeWindowBuffer* graphicBuffer = frame->medbuf->graphicBuffer()->getNativeBuffer();
329         native_window_set_buffers_timestamp(p->mVideoNativeWindow.get(), frame->pts * 1000);
330         int err = p->mVideoNativeWindow.get()->queueBuffer(p->mVideoNativeWindow.get(), graphicBuffer);
331         if (err == 0)
332           frame->medbuf->meta_data()->setInt32(kKeyRendered, 1);
333         frame->medbuf->release();
334         frame->medbuf = NULL;
335         p->UpdateStagefrightTexture();
336
337         if (!p->drop_state)
338         {
339           p->free_mutex.lock();
340           while (!p->free_queue.size())
341             usleep(10000);
342           std::list<std::pair<EGLImageKHR, int> >::iterator itfree = p->free_queue.begin();
343           int cur_slot = itfree->second;
344           p->fbo.BindToTexture(GL_TEXTURE_2D, p->slots[cur_slot].texid);
345           p->fbo.BeginRender();
346
347           glDisable(GL_DEPTH_TEST);
348           //glClear(GL_COLOR_BUFFER_BIT);
349
350           const GLfloat triangleVertices[] = {
351           -1.0f, 1.0f,
352           -1.0f, -1.0f,
353           1.0f, -1.0f,
354           1.0f, 1.0f,
355           };
356
357           glVertexAttribPointer(p->mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);
358           glEnableVertexAttribArray(p->mPositionHandle);
359
360           glUseProgram(p->mPgm);
361           glUniform1i(p->mTexSamplerHandle, 0);
362
363           glBindTexture(GL_TEXTURE_EXTERNAL_OES, p->mVideoTextureId);
364           
365           GLfloat texMatrix[16];
366           // const GLfloat texMatrix[] = {
367             // 1, 0, 0, 0,
368             // 0, -1, 0, 0,
369             // 0, 0, 1, 0,
370             // 0, 1, 0, 1
371           // };
372           p->GetStagefrightTransformMatrix(texMatrix);
373           glUniformMatrix4fv(p->mTexMatrixHandle, 1, GL_FALSE, texMatrix);
374
375           glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
376
377           glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
378           // glDeleteTextures(1, &texid);
379           // eglDestroyImageKHR(p->eglDisplay, img);
380           p->fbo.EndRender();
381
382           glBindTexture(GL_TEXTURE_2D, 0);
383
384           frame->eglimg = p->slots[cur_slot].eglimg;
385           p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
386           p->free_queue.erase(itfree);
387           p->free_mutex.unlock();
388         }
389       }
390
391     #if defined(DEBUG_VERBOSE)
392       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);
393     #endif
394
395       p->out_mutex.lock();
396       p->cur_frame = frame;
397       while (p->cur_frame)
398         p->out_condition.wait(p->out_mutex);
399       p->out_mutex.unlock();
400     }
401     while (!decode_done && !m_bStop);
402     
403     if (p->eglInitialized)
404       p->UninitializeEGL();
405     
406   }
407 };
408
409 /***********************************************************/
410
411 bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
412 {
413 #if defined(DEBUG_VERBOSE)
414   CLog::Log(LOGDEBUG, "%s::Open\n", CLASSNAME);
415 #endif
416
417   CSingleLock lock(g_graphicsContext);
418
419   // stagefright crashes with null size. Trap this...
420   if (!hints.width || !hints.height)
421   {
422     CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"null size, cannot handle");
423     return false;
424   }
425
426   p = new CStageFrightVideoPrivate;
427   p->width     = hints.width;
428   p->height    = hints.height;
429
430   if (g_advancedSettings.m_stagefrightConfig.useSwRenderer)
431     p->quirks |= QuirkSWRender;
432     
433   sp<MetaData> outFormat;
434   int32_t cropLeft, cropTop, cropRight, cropBottom;
435   //Vector<String8> matchingCodecs;
436
437   p->meta = new MetaData;
438   if (p->meta == NULL)
439   {
440     goto fail;
441   }
442
443   const char* mimetype;
444   switch (hints.codec)
445   {
446   case CODEC_ID_H264:
447     if (g_advancedSettings.m_stagefrightConfig.useAVCcodec == 0)
448       return false;
449     mimetype = MEDIA_MIMETYPE_VIDEO_AVC;
450     if ( *(char*)hints.extradata == 1 )
451       p->meta->setData(kKeyAVCC, kTypeAVCC, hints.extradata, hints.extrasize);
452     break;
453   case CODEC_ID_MPEG4:
454     if (g_advancedSettings.m_stagefrightConfig.useMP4codec == 0)
455       return false;
456     mimetype = MEDIA_MIMETYPE_VIDEO_MPEG4;
457     break;
458   case CODEC_ID_MPEG2VIDEO:
459     if (g_advancedSettings.m_stagefrightConfig.useMPEG2codec == 0)
460       return false;
461     mimetype = MEDIA_MIMETYPE_VIDEO_MPEG2;
462     break;
463   case CODEC_ID_VP3:
464   case CODEC_ID_VP6:
465   case CODEC_ID_VP6F:
466   case CODEC_ID_VP8:
467     if (g_advancedSettings.m_stagefrightConfig.useVPXcodec == 0)
468       return false;
469     mimetype = MEDIA_MIMETYPE_VIDEO_VPX;
470     break;
471   case CODEC_ID_VC1:
472   case CODEC_ID_WMV3:
473     if (g_advancedSettings.m_stagefrightConfig.useVC1codec == 0)
474       return false;
475     mimetype = MEDIA_MIMETYPE_VIDEO_WMV;
476     break;
477   default:
478     return false;
479     break;
480   }
481
482   p->meta->setCString(kKeyMIMEType, mimetype);
483   p->meta->setInt32(kKeyWidth, p->width);
484   p->meta->setInt32(kKeyHeight, p->height);
485
486   android::ProcessState::self()->startThreadPool();
487
488   p->source    = new CStageFrightMediaSource(p, p->meta);
489   p->client    = new OMXClient;
490
491   if (p->source == NULL || p->client == NULL)
492   {
493     goto fail;
494   }
495
496   if (p->client->connect() !=  OK)
497   {
498     delete p->client;
499     p->client = NULL;
500     CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot connect OMX client");
501     goto fail;
502   }
503
504   p->mVideoNativeWindow = NULL;
505   if ((p->quirks & QuirkSWRender) == 0)
506   {
507     p->InitStagefrightSurface();
508     native_window_api_connect(p->mVideoNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
509   }
510   
511   p->decoder  = OMXCodec::Create(p->client->interface(), p->meta,
512                                          false, p->source, NULL,
513                                          OMXCodec::kHardwareCodecsOnly | (p->quirks & QuirkSWRender ? OMXCodec::kClientNeedsFramebuffer : 0),
514                                          p->mVideoNativeWindow
515                                          );
516
517   if (!(p->decoder != NULL && p->decoder->start() ==  OK))
518   {
519     p->decoder = NULL;
520     goto fail;
521   }
522
523   outFormat = p->decoder->getFormat();
524
525   if (!outFormat->findInt32(kKeyWidth, &p->width) || !outFormat->findInt32(kKeyHeight, &p->height)
526         || !outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat))
527     goto fail;
528
529   const char *component;
530   if (outFormat->findCString(kKeyDecoderComponent, &component))
531   {
532     CLog::Log(LOGDEBUG, "%s::%s - component: %s\n", CLASSNAME, __func__, component);
533     
534     //Blacklist
535     if (!strncmp(component, "OMX.Nvidia.mp4.decode", 21) && g_advancedSettings.m_stagefrightConfig.useMP4codec != 1)
536     {
537       // Has issues with some XVID encoded MP4. Only fails after actual decoding starts...
538       CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (MP4)");
539       goto fail;
540       
541     }
542     else if (!strncmp(component, "OMX.rk.", 7))
543     {
544       if (g_advancedSettings.m_stagefrightConfig.useAVCcodec != 1 && g_advancedSettings.m_stagefrightConfig.useMP4codec != 1) 
545       {
546         if (p->width % 32 != 0 || p->height % 16 != 0)
547         {
548           // Buggy. Hard crash on non MOD16 height videos and stride errors for non MOD32 width
549           CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (MOD16)");
550           goto fail;
551           
552         }
553       }
554     }
555   }
556
557   cropLeft = cropTop = cropRight = cropBottom = 0;
558   if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
559   {
560     p->x = 0;
561     p->y = 0;
562   }
563   else
564   {
565     p->x = cropLeft;
566     p->y = cropTop;
567     p->width = cropRight - cropLeft + 1;
568     p->height = cropBottom - cropTop + 1;
569   }
570
571   if (!outFormat->findInt32(kKeyStride, &p->videoStride))
572     p->videoStride = p->width;
573   if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
574     p->videoSliceHeight = p->height;
575   
576   for (int i=0; i<INBUFCOUNT; ++i)
577   {
578     p->inbuf[i] = new MediaBuffer(300000);
579     p->inbuf[i]->setObserver(p);
580   }
581   
582   p->decode_thread = new CStageFrightDecodeThread(p);
583   p->decode_thread->Create(true /*autodelete*/);
584
585 #if defined(DEBUG_VERBOSE)
586   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);
587 #endif
588
589   return true;
590
591 fail:
592   if (p->decoder != 0)
593     p->decoder->stop();
594   if (p->client)
595   {
596     p->client->disconnect();
597     delete p->client;
598   }
599   if (p->decoder_component)
600     free(&p->decoder_component);
601   if ((p->quirks & QuirkSWRender) == 0)
602     p->UninitStagefrightSurface();
603   return false;
604 }
605
606 /*** Decode ***/
607 int  CStageFrightVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
608 {
609 #if defined(DEBUG_VERBOSE)
610   unsigned int time = XbmcThreads::SystemClockMillis();
611   CLog::Log(LOGDEBUG, "%s::Decode - d:%p; s:%d; dts:%f; pts:%f\n", CLASSNAME, pData, iSize, dts, pts);
612 #endif
613
614   Frame *frame;
615   int demuxer_bytes = iSize;
616   uint8_t *demuxer_content = pData;
617
618   if (demuxer_content)
619   {
620     frame = (Frame*)malloc(sizeof(Frame));
621     if (!frame)
622       return VC_ERROR;
623
624     frame->status  = OK;
625     if (g_advancedSettings.m_stagefrightConfig.useInputDTS)
626       frame->pts = (dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : ((pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : 0);
627     else
628       frame->pts = (pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : ((dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : 0);
629     frame->medbuf = p->getBuffer(demuxer_bytes);
630     if (!frame->medbuf)
631     {
632       free(frame);
633       return VC_ERROR;
634     }
635     fast_memcpy(frame->medbuf->data(), demuxer_content, demuxer_bytes);
636     frame->medbuf->meta_data()->clear();
637     frame->medbuf->meta_data()->setInt64(kKeyTime, frame->pts);
638     
639     p->in_mutex.lock();
640     p->framecount++;
641     p->in_queue.insert(std::pair<int64_t, Frame*>(p->framecount, frame));
642     p->in_condition.notify();
643     p->in_mutex.unlock();
644   }
645
646   int ret = 0;
647   if (p->inputBufferAvailable() && p->in_queue.size() < INBUFCOUNT)
648     ret |= VC_BUFFER;
649   else
650     usleep(1000);
651   if (p->cur_frame != NULL)
652     ret |= VC_PICTURE;
653 #if defined(DEBUG_VERBOSE)
654   CLog::Log(LOGDEBUG, "%s::Decode: pushed IN frame (%d); tm:%d\n", CLASSNAME,p->in_queue.size(), XbmcThreads::SystemClockMillis() - time);
655 #endif
656
657   return ret;
658 }
659
660 bool CStageFrightVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
661 {
662  #if defined(DEBUG_VERBOSE)
663   unsigned int time = XbmcThreads::SystemClockMillis();
664 #endif
665   if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG && pDvdVideoPicture->eglimg != EGL_NO_IMAGE_KHR)
666     ReleaseBuffer(pDvdVideoPicture->eglimg);
667
668   if (p->prev_frame) {
669     if (p->prev_frame->medbuf)
670       p->prev_frame->medbuf->release();
671     free(p->prev_frame);
672     p->prev_frame = NULL;
673   }
674 #if defined(DEBUG_VERBOSE)
675   CLog::Log(LOGDEBUG, "%s::ClearPicture (%d)\n", CLASSNAME, XbmcThreads::SystemClockMillis() - time);
676 #endif
677
678   return true;
679 }
680
681 bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
682 {
683 #if defined(DEBUG_VERBOSE)
684   unsigned int time = XbmcThreads::SystemClockMillis();
685   CLog::Log(LOGDEBUG, "%s::GetPicture\n", CLASSNAME);
686   if (p->cycle_time != 0)
687     CLog::Log(LOGDEBUG, ">>> cycle dur:%d\n", XbmcThreads::SystemClockMillis() - p->cycle_time);
688   p->cycle_time = time;
689 #endif
690
691   status_t status;
692
693   p->out_mutex.lock();
694   if (!p->cur_frame)
695   {
696     CLog::Log(LOGERROR, "%s::%s - Error getting frame\n", CLASSNAME, __func__);
697     p->out_condition.notify();
698     p->out_mutex.unlock();
699     return false;
700   }
701
702   Frame *frame = p->cur_frame;
703   status  = frame->status;
704
705   pDvdVideoPicture->format = frame->format;
706   pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
707   pDvdVideoPicture->pts = frame->pts;
708   pDvdVideoPicture->iWidth  = frame->width;
709   pDvdVideoPicture->iHeight = frame->height;
710   pDvdVideoPicture->iDisplayWidth = frame->width;
711   pDvdVideoPicture->iDisplayHeight = frame->height;
712   pDvdVideoPicture->iFlags  = DVP_FLAG_ALLOCATED;
713   pDvdVideoPicture->stf = this;
714   pDvdVideoPicture->eglimg = EGL_NO_IMAGE_KHR;
715
716   if (status != OK)
717   {
718     CLog::Log(LOGERROR, "%s::%s - Error getting picture from frame(%d)\n", CLASSNAME, __func__,status);
719     if (frame->medbuf) {
720       frame->medbuf->release();
721     }
722     free(frame);
723     p->cur_frame = NULL;
724     p->out_condition.notify();
725     p->out_mutex.unlock();
726     return false;
727   }
728
729   if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG)
730   {
731     pDvdVideoPicture->eglimg = frame->eglimg;
732   #if defined(DEBUG_VERBOSE)
733     CLog::Log(LOGDEBUG, ">>> pic dts:%f, pts:%llu, img:%p, tm:%d\n", pDvdVideoPicture->dts, frame->pts, pDvdVideoPicture->eglimg, XbmcThreads::SystemClockMillis() - time);
734   #endif
735   } 
736   else if (pDvdVideoPicture->format == RENDER_FMT_YUV420P)
737   {    
738     pDvdVideoPicture->color_range  = 0;
739     pDvdVideoPicture->color_matrix = 4;
740
741     unsigned int luma_pixels = frame->width  * frame->height;
742     unsigned int chroma_pixels = luma_pixels/4;
743     uint8_t* data = NULL;
744     if (frame->medbuf && !p->drop_state)
745     {
746       data = (uint8_t*)((long)frame->medbuf->data() + frame->medbuf->range_offset());
747     }
748     switch (p->videoColorFormat)
749     {
750       case OMX_COLOR_FormatYUV420Planar:
751         pDvdVideoPicture->iLineSize[0] = frame->width;
752         pDvdVideoPicture->iLineSize[1] = frame->width / 2;
753         pDvdVideoPicture->iLineSize[2] = frame->width / 2;
754         pDvdVideoPicture->iLineSize[3] = 0;
755         pDvdVideoPicture->data[0] = data;
756         pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
757         pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
758         pDvdVideoPicture->data[3] = 0;
759         break;
760       case OMX_COLOR_FormatYUV420SemiPlanar:
761       case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
762       case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
763         pDvdVideoPicture->iLineSize[0] = frame->width;
764         pDvdVideoPicture->iLineSize[1] = frame->width;
765         pDvdVideoPicture->iLineSize[2] = 0;
766         pDvdVideoPicture->iLineSize[3] = 0;
767         pDvdVideoPicture->data[0] = data;
768         pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
769         pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
770         pDvdVideoPicture->data[3] = 0;
771         break;
772       default:
773         CLog::Log(LOGERROR, "%s::%s - Unsupported color format(%d)\n", CLASSNAME, __func__,p->videoColorFormat);
774     }
775   #if defined(DEBUG_VERBOSE)
776     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);
777   #endif
778   }
779
780   if (p->drop_state)
781     pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
782
783   p->prev_frame = p->cur_frame;
784   p->cur_frame = NULL;
785   p->out_condition.notify();
786   p->out_mutex.unlock();
787
788   return true;
789 }
790
791 void CStageFrightVideo::Close()
792 {
793 #if defined(DEBUG_VERBOSE)
794   CLog::Log(LOGDEBUG, "%s::Close\n", CLASSNAME);
795 #endif
796
797   Frame *frame;
798
799   if (p->decode_thread && p->decode_thread->IsRunning())
800     p->decode_thread->StopThread(false);
801   p->decode_thread = NULL;
802   p->in_condition.notify();
803
804   // Give decoder_thread time to process EOS, if stuck on reading
805   usleep(50000);
806
807 #if defined(DEBUG_VERBOSE)
808   CLog::Log(LOGDEBUG, "Cleaning OUT\n");
809 #endif
810   p->out_mutex.lock();
811   if (p->cur_frame)
812   {
813     if (p->cur_frame->medbuf)
814       p->cur_frame->medbuf->release();
815     free(p->cur_frame);
816     p->cur_frame = NULL;
817   }
818   p->out_condition.notify();
819   p->out_mutex.unlock();
820
821   if (p->prev_frame)
822   {
823     if (p->prev_frame->medbuf)
824       p->prev_frame->medbuf->release();
825     free(p->prev_frame);
826     p->prev_frame = NULL;
827   }
828
829 #if defined(DEBUG_VERBOSE)
830   CLog::Log(LOGDEBUG, "Stopping omxcodec\n");
831 #endif
832   p->decoder->stop();
833   p->client->disconnect();
834
835 #if defined(DEBUG_VERBOSE)
836   CLog::Log(LOGDEBUG, "Cleaning IN(%d)\n", p->in_queue.size());
837 #endif
838   std::map<int64_t,Frame*>::iterator it;
839   while (!p->in_queue.empty())
840   {
841     it = p->in_queue.begin();
842     frame = it->second;
843     p->in_queue.erase(it);
844     if (frame->medbuf)
845       frame->medbuf->release();
846     free(frame);
847   }
848   
849   if (p->decoder_component)
850     free(&p->decoder_component);
851
852   delete p->client;
853
854   if ((p->quirks & QuirkSWRender) == 0)
855     p->UninitStagefrightSurface();
856
857   for (int i=0; i<INBUFCOUNT; ++i)
858   {
859     p->inbuf[i]->setObserver(NULL);
860     p->inbuf[i]->release();
861   }
862
863   delete p;
864 }
865
866 void CStageFrightVideo::Reset(void)
867 {
868 #if defined(DEBUG_VERBOSE)
869   CLog::Log(LOGDEBUG, "%s::Reset\n", CLASSNAME);
870 #endif
871   Frame* frame;
872   p->in_mutex.lock();
873   std::map<int64_t,Frame*>::iterator it;
874   while (!p->in_queue.empty())
875   {
876     it = p->in_queue.begin();
877     frame = it->second;
878     p->in_queue.erase(it);
879     if (frame->medbuf)
880       frame->medbuf->release();
881     free(frame);
882   }
883   p->resetting = true;
884   p->framecount = 0;
885
886   p->in_mutex.unlock();
887 }
888
889 void CStageFrightVideo::SetDropState(bool bDrop)
890 {
891   if (bDrop == p->drop_state)
892     return;
893
894 #if defined(DEBUG_VERBOSE)
895   CLog::Log(LOGDEBUG, "%s::SetDropState (%d->%d)\n", CLASSNAME,p->drop_state,bDrop);
896 #endif
897
898   p->drop_state = bDrop;
899 }
900
901 void CStageFrightVideo::SetSpeed(int iSpeed)
902 {
903 }
904
905 /***************/
906
907 void CStageFrightVideo::LockBuffer(EGLImageKHR eglimg)
908 {
909  #if defined(DEBUG_VERBOSE)
910   unsigned int time = XbmcThreads::SystemClockMillis();
911 #endif
912   p->free_mutex.lock();
913   std::list<std::pair<EGLImageKHR, int> >::iterator it = p->free_queue.begin();
914   for(;it != p->free_queue.end(); ++it)
915   {
916     if ((*it).first == eglimg)
917       break;
918   }
919   if (it == p->free_queue.end())
920   {
921     p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
922     p->free_mutex.unlock();
923     return;
924   }
925 #if defined(DEBUG_VERBOSE)
926   CLog::Log(LOGDEBUG, "Locking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
927 #endif
928
929   p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
930   p->free_queue.erase(it);
931   p->free_mutex.unlock();
932 }
933
934 void CStageFrightVideo::ReleaseBuffer(EGLImageKHR eglimg)
935 {
936  #if defined(DEBUG_VERBOSE)
937   unsigned int time = XbmcThreads::SystemClockMillis();
938 #endif
939   p->free_mutex.lock();
940   int cnt = 0;
941   std::list<std::pair<EGLImageKHR, int> >::iterator it = p->busy_queue.begin();
942   std::list<std::pair<EGLImageKHR, int> >::iterator itfree;
943   for(;it != p->busy_queue.end(); ++it)
944   {
945     if ((*it).first == eglimg)
946     {
947       cnt++;
948       if (cnt==1)
949         itfree = it;
950       else
951         break;
952     }
953   }
954   if (it == p->busy_queue.end() && !cnt)
955   {
956     p->free_mutex.unlock();
957     return;
958   }
959 #if defined(DEBUG_VERBOSE)
960   CLog::Log(LOGDEBUG, "Unlocking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
961 #endif
962
963   if (cnt==1)
964   {
965     p->free_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
966     p->busy_queue.erase(itfree);
967   }
968   p->free_mutex.unlock();
969 }