FIX: [stagefright] fixes and refactors (probable fix for 60min stuttering)
authorChris "Koying" Browet <cbro@semperpax.com>
Fri, 15 Nov 2013 10:22:09 +0000 (11:22 +0100)
committerChris "Koying" Browet <cbro@semperpax.com>
Sat, 16 Nov 2013 08:27:53 +0000 (09:27 +0100)
xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecStageFright.cpp
xbmc/cores/dvdplayer/DVDCodecs/Video/DllLibStageFrightCodec.h
xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.cpp
xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.h
xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.cpp
xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.h
xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.cpp
xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.h

index 46f4442..94a8b49 100644 (file)
@@ -855,17 +855,20 @@ inline void CLinuxRendererGLES::ReorderDrawPoints()
 
 void CLinuxRendererGLES::ReleaseBuffer(int idx)
 {
-#ifdef HAVE_VIDEOTOOLBOXDECODER
   YUVBUFFER &buf = m_buffers[idx];
-
-  if (buf.cvBufferRef)
-    CVBufferRelease(buf.cvBufferRef);
-  buf.cvBufferRef = NULL;
+#ifdef HAVE_VIDEOTOOLBOXDECODER
+  if (m_renderMethod & RENDER_CVREF )
+  {
+    if (buf.cvBufferRef)
+      CVBufferRelease(buf.cvBufferRef);
+    buf.cvBufferRef = NULL;
+  }
 #endif
 #if defined(TARGET_ANDROID)
-  YUVBUFFER &buf = m_buffers[idx];
-
-  SAFE_RELEASE(buf.mediacodec);
+  if ( m_renderMethod & RENDER_MEDIACODEC )
+  {
+    SAFE_RELEASE(buf.mediacodec);
+  }
 #endif
 }
 
@@ -2305,11 +2308,15 @@ void CLinuxRendererGLES::UploadEGLIMGTexture(int index)
 void CLinuxRendererGLES::DeleteEGLIMGTexture(int index)
 {
 #ifdef HAS_LIBSTAGEFRIGHT
-  YUVPLANE &plane = m_buffers[index].fields[0][0];
+  YUVBUFFER &buf = m_buffers[index];
+  YUVPLANE &plane = buf.fields[0][0];
 
   if(plane.id && glIsTexture(plane.id))
     glDeleteTextures(1, &plane.id);
   plane.id = 0;
+
+  buf.stf = NULL;
+  buf.eglimg = EGL_NO_IMAGE_KHR;
 #endif
 }
 bool CLinuxRendererGLES::CreateEGLIMGTexture(int index)
index f5615db..b05ef56 100644 (file)
@@ -137,7 +137,7 @@ void CDVDVideoCodecStageFright::Dispose()
   }
   if (m_stf_handle)
   {
-    m_stf_dll->stf_Close(m_stf_handle);
+    m_stf_dll->stf_Dispose(m_stf_handle);
     m_stf_dll->destroy_stf(m_stf_handle);
     m_stf_handle = NULL;
   }
index cf75aca..fcc497b 100644 (file)
@@ -41,7 +41,7 @@ public:
   virtual void destroy_stf(void*)=0;
   
   virtual bool stf_Open(void*, CDVDStreamInfo &hints) = 0;
-  virtual void stf_Close(void*) = 0;
+  virtual void stf_Dispose(void*) = 0;
   virtual int  stf_Decode(void*, uint8_t *pData, int iSize, double dts, double pts) = 0;
   virtual void stf_Reset(void*) = 0;
   virtual bool stf_GetPicture(void*, DVDVideoPicture *pDvdVideoPicture) = 0;
@@ -59,7 +59,7 @@ class DllLibStageFrightCodec : public DllDynamic, DllLibStageFrightCodecInterfac
   DEFINE_METHOD4(void*, create_stf, (CApplication* p1, CApplicationMessenger* p2, CWinSystemEGL* p3, CAdvancedSettings* p4))
   DEFINE_METHOD1(void, destroy_stf, (void* p1))
   DEFINE_METHOD2(bool, stf_Open, (void* p1, CDVDStreamInfo &p2))
-  DEFINE_METHOD1(void, stf_Close, (void* p1))
+  DEFINE_METHOD1(void, stf_Dispose, (void* p1))
   DEFINE_METHOD5(int, stf_Decode, (void* p1, uint8_t *p2, int p3, double p4, double p5))
   DEFINE_METHOD1(void, stf_Reset, (void* p1))
   DEFINE_METHOD2(bool, stf_GetPicture, (void* p1, DVDVideoPicture * p2))
@@ -72,7 +72,7 @@ class DllLibStageFrightCodec : public DllDynamic, DllLibStageFrightCodecInterfac
     RESOLVE_METHOD(create_stf)
     RESOLVE_METHOD(destroy_stf)
     RESOLVE_METHOD(stf_Open)
-    RESOLVE_METHOD(stf_Close)
+    RESOLVE_METHOD(stf_Dispose)
     RESOLVE_METHOD(stf_Decode)
     RESOLVE_METHOD(stf_Reset)
     RESOLVE_METHOD(stf_GetPicture)
index a9a90bd..6366bfc 100644 (file)
@@ -39,9 +39,9 @@ bool stf_Open(void* stf, CDVDStreamInfo &hints)
   return ((CStageFrightVideo*)stf)->Open(hints);
 }
 
-void stf_Close(void* stf)
+void stf_Dispose(void* stf)
 {
-  ((CStageFrightVideo*)stf)->Close();
+  ((CStageFrightVideo*)stf)->Dispose();
 }
 
 int  stf_Decode(void* stf, uint8_t *pData, int iSize, double dts, double pts)
index c54ae97..ffd9700 100644 (file)
@@ -34,7 +34,7 @@ extern "C"
   void destroy_stf(void*);
 
   bool stf_Open(void*, CDVDStreamInfo &hints);
-  void stf_Close(void*);
+  void stf_Dispose(void*);
   int  stf_Decode(void*, uint8_t *pData, int iSize, double dts, double pts);
   void stf_Reset(void*);
   bool stf_GetPicture(void*, DVDVideoPicture *pDvdVideoPicture);
index 615dea1..089b3e9 100644 (file)
@@ -36,6 +36,7 @@
 #include "Application.h"
 #include "ApplicationMessenger.h"
 #include "settings/AdvancedSettings.h"
+#include "android/jni/Build.h"
 
 #include "xbmc/guilib/FrameBufferObject.h"
 
@@ -126,8 +127,8 @@ public:
       return VC_ERROR;
     }
 
-    std::map<int64_t,Frame*>::iterator it = p->in_queue.begin();
-    frame = it->second;
+    std::list<Frame*>::iterator it = p->in_queue.begin();
+    frame = *it;
     ret = frame->status;
     *buffer = frame->medbuf;
 
@@ -178,10 +179,8 @@ public:
   void Process()
   {
     Frame* frame;
-    int32_t w, h, dw, dh;
+    int32_t w, h;
     int decode_done = 0;
-    int32_t keyframe = 0;
-    int32_t unreadable = 0;
     MediaSource::ReadOptions readopt;
     // GLuint texid;
 
@@ -238,18 +237,6 @@ public:
         sp<MetaData> outFormat = p->decoder->getFormat();
         outFormat->findInt32(kKeyWidth , &w);
         outFormat->findInt32(kKeyHeight, &h);
-
-        // The OMX.SEC decoder doesn't signal the modified width/height
-        if (p->decoder_component && (w & 15 || h & 15) && !strncmp(p->decoder_component, "OMX.SEC", 7))
-        {
-          if (((w + 15)&~15) * ((h + 15)&~15) * 3/2 == frame->medbuf->range_length())
-          {
-            w = (w + 15)&~15;
-            h = (h + 15)&~15;
-            frame->width = w;
-            frame->height = h;
-          }
-        }
         frame->medbuf->meta_data()->findInt64(kKeyTime, &(frame->pts));
       }
       else if (frame->status == INFO_FORMAT_CHANGED)
@@ -307,19 +294,10 @@ public:
         }
         else if (p->texwidth != frame->width || p->texheight != frame->height)
         {
-          p->UninitializeEGL();
+          p->ReleaseEGL();
           p->InitializeEGL(frame->width, frame->height);
         }
 
-        if (p->free_queue.empty())
-        {
-          CLog::Log(LOGERROR, "%s::%s - Error: No free output buffers\n", CLASSNAME, __func__);
-          if (frame->medbuf)
-            frame->medbuf->release();
-          free(frame);
-          continue;
-        }
-
         ANativeWindowBuffer* graphicBuffer = frame->medbuf->graphicBuffer()->getNativeBuffer();
         native_window_set_buffers_timestamp(p->mVideoNativeWindow.get(), frame->pts * 1000);
         int err = p->mVideoNativeWindow.get()->queueBuffer(p->mVideoNativeWindow.get(), graphicBuffer);
@@ -332,11 +310,15 @@ public:
         if (!p->drop_state)
         {
           p->free_mutex.lock();
-          while (!p->free_queue.size())
-            usleep(10000);
-          std::list<std::pair<EGLImageKHR, int> >::iterator itfree = p->free_queue.begin();
-          int cur_slot = itfree->second;
-          p->fbo.BindToTexture(GL_TEXTURE_2D, p->slots[cur_slot].texid);
+
+          stSlot* cur_slot = p->getFreeSlot();
+          if (!cur_slot)
+          {
+            CLog::Log(LOGERROR, "STF: No free output buffers\n");
+            continue;
+          }
+
+          p->fbo.BindToTexture(GL_TEXTURE_2D, cur_slot->texid);
           p->fbo.BeginRender();
 
           glDisable(GL_DEPTH_TEST);
@@ -358,33 +340,23 @@ public:
           glBindTexture(GL_TEXTURE_EXTERNAL_OES, p->mVideoTextureId);
 
           GLfloat texMatrix[16];
-          // const GLfloat texMatrix[] = {
-            // 1, 0, 0, 0,
-            // 0, -1, 0, 0,
-            // 0, 0, 1, 0,
-            // 0, 1, 0, 1
-          // };
           p->GetSurfaceTextureTransformMatrix(texMatrix);
           glUniformMatrix4fv(p->mTexMatrixHandle, 1, GL_FALSE, texMatrix);
 
           glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
           glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
-          // glDeleteTextures(1, &texid);
-          // eglDestroyImageKHR(p->eglDisplay, img);
           p->fbo.EndRender();
 
           glBindTexture(GL_TEXTURE_2D, 0);
 
-          frame->eglimg = p->slots[cur_slot].eglimg;
-          p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
-          p->free_queue.erase(itfree);
+          frame->eglimg = cur_slot->eglimg;
           p->free_mutex.unlock();
         }
       }
 
     #if defined(DEBUG_VERBOSE)
-      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);
+      CLog::Log(LOGDEBUG, "%s: >>> pushed OUT frame; w:%d, h:%d, img:%p, tm:%d\n", CLASSNAME, frame->width, frame->height, frame->eglimg, XbmcThreads::SystemClockMillis() - time);
     #endif
 
       p->out_mutex.lock();
@@ -396,7 +368,7 @@ public:
     while (!decode_done && !m_bStop);
 
     if (p->eglInitialized)
-      p->UninitializeEGL();
+      p->ReleaseEGL();
 
   }
 };
@@ -426,6 +398,11 @@ bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
   CLog::Log(LOGDEBUG, "%s::Open\n", CLASSNAME);
 #endif
 
+  CLog::Log(LOGDEBUG,
+        "CStageFrightVideo - p:%s, d:%s, b:%s - m:%s, b:%s, m:%s, h:%s",
+        CJNIBuild::PRODUCT.c_str(), CJNIBuild::DEVICE.c_str(), CJNIBuild::BOARD.c_str(),
+        CJNIBuild::MANUFACTURER.c_str(), CJNIBuild::BRAND.c_str(), CJNIBuild::MODEL.c_str(), CJNIBuild::HARDWARE.c_str());
+
   CSingleLock lock(g_graphicsContext);
 
   // stagefright crashes with null size. Trap this...
@@ -440,10 +417,6 @@ bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
   if (p->m_g_advancedSettings->m_stagefrightConfig.useSwRenderer)
     p->quirks |= QuirkSWRender;
 
-  sp<MetaData> outFormat;
-  int32_t cropLeft, cropTop, cropRight, cropBottom;
-  //Vector<String8> matchingCodecs;
-
   p->meta = new MetaData;
   if (p->meta == NULL)
   {
@@ -501,12 +474,17 @@ bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
 
   if (p->source == NULL || p->client == NULL)
   {
+    p->meta = NULL;
+    p->source = NULL;
+    p->decoder = NULL;
     CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot obtain source / client");
     return false;
   }
 
   if (p->client->connect() !=  OK)
   {
+    p->meta = NULL;
+    p->source = NULL;
     delete p->client;
     p->client = NULL;
     CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot connect OMX client");
@@ -516,6 +494,8 @@ bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
   if ((p->quirks & QuirkSWRender) == 0)
     if (!p->InitSurfaceTexture())
     {
+      p->meta = NULL;
+      p->source = NULL;
       delete p->client;
       p->client = NULL;
       CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot allocate texture");
@@ -530,15 +510,22 @@ bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
 
   if (!(p->decoder != NULL && p->decoder->start() ==  OK))
   {
+    p->meta = NULL;
+    p->source = NULL;
     p->decoder = NULL;
     return false;
   }
 
-  outFormat = p->decoder->getFormat();
+  sp<MetaData> outFormat = p->decoder->getFormat();
 
   if (!outFormat->findInt32(kKeyWidth, &p->width) || !outFormat->findInt32(kKeyHeight, &p->height)
         || !outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat))
+  {
+    p->meta = NULL;
+    p->source = NULL;
+    p->decoder = NULL;
     return false;
+  }
 
   const char *component;
   if (outFormat->findCString(kKeyDecoderComponent, &component))
@@ -560,6 +547,7 @@ bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
     }
   }
 
+  int32_t cropLeft, cropTop, cropRight, cropBottom;
   cropLeft = cropTop = cropRight = cropBottom = 0;
   if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
   {
@@ -630,6 +618,7 @@ int  CStageFrightVideo::Decode(uint8_t *pData, int iSize, double dts, double pts
     frame->medbuf = p->getBuffer(demuxer_bytes);
     if (!frame->medbuf)
     {
+      CLog::Log(LOGWARNING, "STF: Cannot get input buffer\n");
       free(frame);
       return VC_ERROR;
     }
@@ -639,8 +628,7 @@ int  CStageFrightVideo::Decode(uint8_t *pData, int iSize, double dts, double pts
     frame->medbuf->meta_data()->setInt64(kKeyTime, frame->pts);
 
     p->in_mutex.lock();
-    p->framecount++;
-    p->in_queue.insert(std::pair<int64_t, Frame*>(p->framecount, frame));
+    p->in_queue.push_back(frame);
     p->in_condition.notify();
     p->in_mutex.unlock();
   }
@@ -729,6 +717,10 @@ bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
   if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG)
   {
     pDvdVideoPicture->eglimg = frame->eglimg;
+    if (pDvdVideoPicture->eglimg == EGL_NO_IMAGE_KHR)
+      pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
+    else
+      LockBuffer(pDvdVideoPicture->eglimg);
   #if defined(DEBUG_VERBOSE)
     CLog::Log(LOGDEBUG, ">>> pic dts:%f, pts:%llu, img:%p, tm:%d\n", pDvdVideoPicture->dts, frame->pts, pDvdVideoPicture->eglimg, XbmcThreads::SystemClockMillis() - time);
   #endif
@@ -788,7 +780,7 @@ bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
   return true;
 }
 
-void CStageFrightVideo::Close()
+void CStageFrightVideo::Dispose()
 {
 #if defined(DEBUG_VERBOSE)
   CLog::Log(LOGDEBUG, "%s::Close\n", CLASSNAME);
@@ -830,24 +822,41 @@ void CStageFrightVideo::Close()
   CLog::Log(LOGDEBUG, "Stopping omxcodec\n");
 #endif
   if (p->decoder != NULL)
+  {
     p->decoder->stop();
+    p->decoder = NULL;
+  }
   if (p->client)
+  {
     p->client->disconnect();
+    delete p->client;
+  }
+  p->meta = NULL;
 
 #if defined(DEBUG_VERBOSE)
   CLog::Log(LOGDEBUG, "Cleaning IN(%d)\n", p->in_queue.size());
 #endif
-  std::map<int64_t,Frame*>::iterator it;
+  std::list<Frame*>::iterator it;
   while (!p->in_queue.empty())
   {
     it = p->in_queue.begin();
-    frame = it->second;
+    frame = *it;
     p->in_queue.erase(it);
     if (frame->medbuf)
       frame->medbuf->release();
     free(frame);
   }
-  
+  for (int i=0; i<INBUFCOUNT; ++i)
+  {
+    if (p->inbuf[i])
+    {
+      p->inbuf[i]->setObserver(NULL);
+      p->inbuf[i]->release();
+      p->inbuf[i] = NULL;
+    }
+  }
+  p->source = NULL;
+
 #if defined(DEBUG_VERBOSE)
   CLog::Log(LOGDEBUG, "Cleaning libstagefright\n", p->in_queue.size());
 #endif
@@ -859,18 +868,6 @@ void CStageFrightVideo::Close()
 #endif
   if (p->decoder_component)
     free(&p->decoder_component);
-
-  delete p->client;
-
-  for (int i=0; i<INBUFCOUNT; ++i)
-  {
-    if (p->inbuf[i])
-    {
-      p->inbuf[i]->setObserver(NULL);
-      p->inbuf[i]->release();
-      p->inbuf[i] = NULL;
-    }
-  }
 }
 
 void CStageFrightVideo::Reset(void)
@@ -880,18 +877,17 @@ void CStageFrightVideo::Reset(void)
 #endif
   Frame* frame;
   p->in_mutex.lock();
-  std::map<int64_t,Frame*>::iterator it;
+  std::list<Frame*>::iterator it;
   while (!p->in_queue.empty())
   {
     it = p->in_queue.begin();
-    frame = it->second;
+    frame = *it;
     p->in_queue.erase(it);
     if (frame->medbuf)
       frame->medbuf->release();
     free(frame);
   }
   p->resetting = true;
-  p->framecount = 0;
 
   p->in_mutex.unlock();
 }
@@ -916,64 +912,48 @@ void CStageFrightVideo::SetSpeed(int iSpeed)
 
 void CStageFrightVideo::LockBuffer(EGLImageKHR eglimg)
 {
- #if defined(DEBUG_VERBOSE)
+#if defined(DEBUG_VERBOSE)
   unsigned int time = XbmcThreads::SystemClockMillis();
 #endif
   p->free_mutex.lock();
-  std::list<std::pair<EGLImageKHR, int> >::iterator it = p->free_queue.begin();
-  for(;it != p->free_queue.end(); ++it)
+  stSlot* slot = p->getSlot(eglimg);
+  if (!slot)
   {
-    if ((*it).first == eglimg)
-      break;
-  }
-  if (it == p->free_queue.end())
-  {
-    p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
+    CLog::Log(LOGDEBUG, "STF: LockBuffer: Unknown img(%p)", eglimg);
     p->free_mutex.unlock();
     return;
   }
+  slot->use_cnt++;
+
 #if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "Locking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
+  CLog::Log(LOGDEBUG, "STF: LockBuffer: Locking %p: cnt:%d tm:%d\n", eglimg, slot->use_cnt, XbmcThreads::SystemClockMillis() - time);
 #endif
-
-  p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
-  p->free_queue.erase(it);
   p->free_mutex.unlock();
 }
 
 void CStageFrightVideo::ReleaseBuffer(EGLImageKHR eglimg)
 {
- #if defined(DEBUG_VERBOSE)
+#if defined(DEBUG_VERBOSE)
   unsigned int time = XbmcThreads::SystemClockMillis();
 #endif
   p->free_mutex.lock();
-  int cnt = 0;
-  std::list<std::pair<EGLImageKHR, int> >::iterator it = p->busy_queue.begin();
-  std::list<std::pair<EGLImageKHR, int> >::iterator itfree;
-  for(;it != p->busy_queue.end(); ++it)
+  stSlot* slot = p->getSlot(eglimg);
+  if (!slot)
   {
-    if ((*it).first == eglimg)
-    {
-      cnt++;
-      if (cnt==1)
-        itfree = it;
-      else
-        break;
-    }
+    CLog::Log(LOGDEBUG, "STF: ReleaseBuffer: Unknown img(%p)", eglimg);
+    p->free_mutex.unlock();
+    return;
   }
-  if (it == p->busy_queue.end() && !cnt)
+  if (slot->use_cnt == 0)
   {
+    CLog::Log(LOGDEBUG, "STF: ReleaseBuffer: already unlocked img(%p)", eglimg);
     p->free_mutex.unlock();
     return;
   }
+  slot->use_cnt--;
+
 #if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "Unlocking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
+  CLog::Log(LOGDEBUG, "STF: ReleaseBuffer: Unlocking %p: cnt:%d tm:%d\n", eglimg, slot->use_cnt, XbmcThreads::SystemClockMillis() - time);
 #endif
-
-  if (cnt==1)
-  {
-    p->free_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
-    p->busy_queue.erase(itfree);
-  }
   p->free_mutex.unlock();
 }
index 44c9100..f36db67 100644 (file)
@@ -39,7 +39,7 @@ public:
   virtual ~CStageFrightVideo();
 
   bool Open(CDVDStreamInfo &hints);
-  void Close(void);
+  void Dispose(void);
   int  Decode(uint8_t *pData, int iSize, double dts, double pts);
   void Reset(void);
   bool GetPicture(DVDVideoPicture *pDvdVideoPicture);
index 0c3e2ed..0390233 100644 (file)
@@ -105,8 +105,8 @@ MediaBuffer* CStageFrightVideoPrivate::getBuffer(size_t size)
     inbuf[i]->setObserver(this);
   }
 
+  inbuf[i]->reset();
   inbuf[i]->add_ref();
-  inbuf[i]->set_range(0, size);
   return inbuf[i];
 }
 
@@ -119,6 +119,24 @@ bool CStageFrightVideoPrivate::inputBufferAvailable()
   return false;
 }
 
+stSlot* CStageFrightVideoPrivate::getSlot(EGLImageKHR eglimg)
+{
+  for (int i=0; i<NUMFBOTEX; ++i)
+    if (texslots[i].eglimg == eglimg)
+      return &(texslots[i]);
+
+  return NULL;
+}
+
+stSlot* CStageFrightVideoPrivate::getFreeSlot()
+{
+  for (int i=0; i<NUMFBOTEX; ++i)
+    if (texslots[i].use_cnt == 0)
+      return &(texslots[i]);
+
+  return NULL;
+}
+
 void CStageFrightVideoPrivate::loadOESShader(GLenum shaderType, const char* pSource, GLuint* outShader)
 {
 #if defined(DEBUG_VERBOSE)
@@ -271,8 +289,8 @@ void CStageFrightVideoPrivate::InitializeEGL(int w, int h)
 
   for (int i=0; i<NUMFBOTEX; ++i)
   {
-    glGenTextures(1, &(slots[i].texid));
-    glBindTexture(GL_TEXTURE_2D,  slots[i].texid);
+    glGenTextures(1, &(texslots[i].texid));
+    glBindTexture(GL_TEXTURE_2D,  texslots[i].texid);
 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texwidth, texheight, 0,
            GL_RGBA, GL_UNSIGNED_BYTE, 0);
@@ -283,9 +301,8 @@ void CStageFrightVideoPrivate::InitializeEGL(int w, int h)
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
-    slots[i].eglimg = eglCreateImageKHR(eglDisplay, eglContext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(slots[i].texid),imageAttributes);
-    free_queue.push_back(std::pair<EGLImageKHR, int>(slots[i].eglimg, i));
-
+    texslots[i].eglimg = eglCreateImageKHR(eglDisplay, eglContext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(texslots[i].texid),imageAttributes);
+    texslots[i].use_cnt = 0;
   }
   glBindTexture(GL_TEXTURE_2D,  0);
 
@@ -298,7 +315,7 @@ void CStageFrightVideoPrivate::InitializeEGL(int w, int h)
 #endif
 }
 
-void CStageFrightVideoPrivate::UninitializeEGL()
+void CStageFrightVideoPrivate::ReleaseEGL()
 {
 #if defined(DEBUG_VERBOSE)
   CLog::Log(LOGDEBUG, "%s: >>> UninitializeEGL\n", CLASSNAME);
@@ -306,8 +323,8 @@ void CStageFrightVideoPrivate::UninitializeEGL()
   fbo.Cleanup();
   for (int i=0; i<NUMFBOTEX; ++i)
   {
-    glDeleteTextures(1, &(slots[i].texid));
-    eglDestroyImageKHR(eglDisplay, slots[i].eglimg);
+    glDeleteTextures(1, &(texslots[i].texid));
+    eglDestroyImageKHR(eglDisplay, texslots[i].eglimg);
   }
 
   if (eglContext != EGL_NO_CONTEXT)
@@ -356,17 +373,6 @@ bool CStageFrightVideoPrivate::InitSurfaceTexture()
     glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     glBindTexture(  GL_TEXTURE_EXTERNAL_OES, 0);
     mVideoTextureId = texture_id;
-
-    mSurfTexture = new CJNISurfaceTexture(mVideoTextureId);
-    mSurface = new CJNISurface(*mSurfTexture);
-
-    JNIEnv* env = xbmc_jnienv();
-    mVideoNativeWindow = ANativeWindow_fromSurface(env, mSurface->get_raw());
-    native_window_api_connect(mVideoNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
-
-  #if defined(DEBUG_VERBOSE)
-    CLog::Log(LOGDEBUG, "%s: <<< InitSurfaceTexture\n", CLASSNAME);
-  #endif
   }
   else
   {
@@ -380,6 +386,17 @@ bool CStageFrightVideoPrivate::InitSurfaceTexture()
 
     // wait for it.
     m_g_applicationMessenger->SendMessage(msg, true);
+
+    mSurfTexture = new CJNISurfaceTexture(mVideoTextureId);
+    mSurface = new CJNISurface(*mSurfTexture);
+
+    JNIEnv* env = xbmc_jnienv();
+    mVideoNativeWindow = ANativeWindow_fromSurface(env, mSurface->get_raw());
+    native_window_api_connect(mVideoNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
+
+  #if defined(DEBUG_VERBOSE)
+    CLog::Log(LOGDEBUG, "%s: <<< InitSurfaceTexture texid(%d) natwin(%p)\n", CLASSNAME, mVideoTextureId, mVideoNativeWindow.get());
+  #endif
   }
 
   return (mVideoTextureId != -1);
@@ -395,7 +412,7 @@ void CStageFrightVideoPrivate::ReleaseSurfaceTexture()
 
   native_window_api_disconnect(mVideoNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
   ANativeWindow_release(mVideoNativeWindow.get());
-  mVideoNativeWindow = NULL;
+  mVideoNativeWindow.clear();
 
   mSurface->release();
   mSurfTexture->release();
@@ -403,7 +420,8 @@ void CStageFrightVideoPrivate::ReleaseSurfaceTexture()
   delete mSurface;
   delete mSurfTexture;
 
-  glDeleteTextures(1, &mVideoTextureId);
+  if (mVideoTextureId > 0)
+    glDeleteTextures(1, &mVideoTextureId);
 #if defined(DEBUG_VERBOSE)
   CLog::Log(LOGDEBUG, "%s: <<< ReleaseSurfaceTexture\n", CLASSNAME);
 #endif
index 3b7e152..34e9c50 100644 (file)
@@ -61,10 +61,11 @@ class CApplicationMessenger;
 
 using namespace android;
 
-struct tex_slot
+struct stSlot
 {
   GLuint texid;
   EGLImageKHR eglimg;
+  int use_cnt;
 };
 
 struct Frame
@@ -93,11 +94,14 @@ public:
   MediaBuffer* getBuffer(size_t size);
   bool inputBufferAvailable();
 
+  stSlot* getSlot(EGLImageKHR eglimg);
+  stSlot* getFreeSlot();
+
   void loadOESShader(GLenum shaderType, const char* pSource, GLuint* outShader);
   void createOESProgram(const char* pVertexSource, const char* pFragmentSource, GLuint* outPgm);
   void OES_shader_setUp();
   void InitializeEGL(int w, int h);
-  void UninitializeEGL();
+  void ReleaseEGL();
 
 public:
   CStageFrightDecodeThread* decode_thread;
@@ -122,13 +126,11 @@ public:
   EGLContext eglContext;
   bool eglInitialized;
 
-  tex_slot slots[NUMFBOTEX];
-  std::list< std::pair<EGLImageKHR, int> > free_queue;
-  std::list< std::pair<EGLImageKHR, int> > busy_queue;
+  stSlot texslots[NUMFBOTEX];
 
   sp<MetaData> meta;
   int64_t framecount;
-  std::map<int64_t, Frame*> in_queue;
+  std::list<Frame*> in_queue;
   std::map<int64_t, Frame*> out_queue;
   CCriticalSection in_mutex;
   CCriticalSection out_mutex;