aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Browet <koying@semperpax.com>2013-11-16 12:50:10 -0800
committerChris Browet <koying@semperpax.com>2013-11-16 12:50:10 -0800
commit06e6fb22594c91733dd2141ca8ae221fa8481101 (patch)
tree343bfc21bc5680df66bcda7ea73b2f5a4a8633e0
parent3540cc97b3b003fde5ab9a1cbbe91788f64f345d (diff)
parent60f2fb151a21ca750a16695c313c26030c796665 (diff)
Merge pull request #3657 from koying/quickpr
Stagefright fixes
-rw-r--r--xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp25
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecStageFright.cpp6
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Video/DllLibStageFrightCodec.h12
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.cpp8
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.h6
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.cpp210
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.h6
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.cpp124
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.h27
9 files changed, 245 insertions, 179 deletions
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
index 46f4442b43..94a8b49dbc 100644
--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
@@ -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)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecStageFright.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecStageFright.cpp
index ee7fbe0ee4..b05ef561dc 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecStageFright.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecStageFright.cpp
@@ -32,6 +32,8 @@
#include "DVDStreamInfo.h"
#include "DVDVideoCodecStageFright.h"
#include "utils/log.h"
+#include "Application.h"
+#include "ApplicationMessenger.h"
#include "windowing/WindowingFactory.h"
#include "settings/AdvancedSettings.h"
@@ -108,7 +110,7 @@ bool CDVDVideoCodecStageFright::Open(CDVDStreamInfo &hints, CDVDCodecOptions &op
return false;
m_stf_dll->EnableDelayedUnload(false);
- m_stf_handle = m_stf_dll->create_stf(&g_Windowing, &g_advancedSettings);
+ m_stf_handle = m_stf_dll->create_stf(&g_application, &CApplicationMessenger::Get(), &g_Windowing, &g_advancedSettings);
if (!m_stf_dll->stf_Open(m_stf_handle, hints))
{
@@ -135,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;
}
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DllLibStageFrightCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DllLibStageFrightCodec.h
index 442746b8a4..fcc497bc10 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DllLibStageFrightCodec.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DllLibStageFrightCodec.h
@@ -27,6 +27,8 @@
#include "DynamicDll.h"
#include "DVDVideoCodec.h"
+class CApplication;
+class CApplicationMessenger;
class CWinSystemEGL;
class CAdvancedSettings;
@@ -35,11 +37,11 @@ class DllLibStageFrightCodecInterface
public:
virtual ~DllLibStageFrightCodecInterface() {}
- virtual void* create_stf(CWinSystemEGL* windowing, CAdvancedSettings* advsettings)=0;
+ virtual void* create_stf(CApplication* application, CApplicationMessenger* applicationMessenger, CWinSystemEGL* windowing, CAdvancedSettings* advsettings)=0;
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;
@@ -54,10 +56,10 @@ public:
class DllLibStageFrightCodec : public DllDynamic, DllLibStageFrightCodecInterface
{
DECLARE_DLL_WRAPPER(DllLibStageFrightCodec, DLL_PATH_LIBSTAGEFRIGHTICS)
- DEFINE_METHOD2(void*, create_stf, (CWinSystemEGL* p1, CAdvancedSettings* p2))
+ 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))
@@ -70,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)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.cpp
index b2305d7449..6366bfc095 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.cpp
@@ -24,9 +24,9 @@
#include "windowing/WindowingFactory.h"
#include "settings/AdvancedSettings.h"
-void* create_stf(CWinSystemEGL* windowing, CAdvancedSettings* advsettings)
+void* create_stf(CApplication* application, CApplicationMessenger* applicationMessenger, CWinSystemEGL* windowing, CAdvancedSettings* advsettings)
{
- return (void*)new CStageFrightVideo(windowing, advsettings);
+ return (void*)new CStageFrightVideo(application, applicationMessenger, windowing, advsettings);
}
void destroy_stf(void* stf)
@@ -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)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.h
index 6c4eebf63d..ffd9700067 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.h
@@ -23,16 +23,18 @@
#include "DVDVideoCodec.h"
class CStageFrightVideo;
+class CApplication;
+class CApplicationMessenger;
class CWinSystemEGL;
class CAdvancedSettings;
extern "C"
{
- void* create_stf(CWinSystemEGL* windowing, CAdvancedSettings* advsettings);
+ void* create_stf(CApplication* application, CApplicationMessenger* applicationMessenger, CWinSystemEGL* windowing, CAdvancedSettings* advsettings);
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);
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.cpp
index 1165525904..089b3e9003 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.cpp
@@ -33,7 +33,10 @@
#include "utils/fastmemcpy.h"
#include "threads/Thread.h"
#include "threads/Event.h"
+#include "Application.h"
+#include "ApplicationMessenger.h"
#include "settings/AdvancedSettings.h"
+#include "android/jni/Build.h"
#include "xbmc/guilib/FrameBufferObject.h"
@@ -124,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;
@@ -176,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;
@@ -236,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)
@@ -305,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);
@@ -325,16 +305,20 @@ public:
frame->medbuf->meta_data()->setInt32(kKeyRendered, 1);
frame->medbuf->release();
frame->medbuf = NULL;
- p->UpdateStagefrightTexture();
+ p->UpdateSurfaceTexture();
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);
@@ -356,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->GetStagefrightTransformMatrix(texMatrix);
+ 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();
@@ -394,19 +368,21 @@ public:
while (!decode_done && !m_bStop);
if (p->eglInitialized)
- p->UninitializeEGL();
+ p->ReleaseEGL();
}
};
/***********************************************************/
-CStageFrightVideo::CStageFrightVideo(CWinSystemEGL* windowing, CAdvancedSettings* advsettings)
+CStageFrightVideo::CStageFrightVideo(CApplication* application, CApplicationMessenger* applicationMessenger, CWinSystemEGL* windowing, CAdvancedSettings* advsettings)
{
#if defined(DEBUG_VERBOSE)
CLog::Log(LOGDEBUG, "%s::ctor: %d\n", CLASSNAME, sizeof(CStageFrightVideo));
#endif
p = new CStageFrightVideoPrivate;
+ p->m_g_application = application;
+ p->m_g_applicationMessenger = applicationMessenger;
p->m_g_Windowing = windowing;
p->m_g_advancedSettings = advsettings;
}
@@ -422,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...
@@ -436,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)
{
@@ -497,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");
@@ -510,7 +492,15 @@ bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
}
if ((p->quirks & QuirkSWRender) == 0)
- p->InitStagefrightSurface();
+ 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");
+ return false;
+ }
p->decoder = OMXCodec::Create(p->client->interface(), p->meta,
false, p->source, NULL,
@@ -520,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))
@@ -550,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))
{
@@ -620,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;
}
@@ -629,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();
}
@@ -719,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
@@ -778,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);
@@ -820,47 +822,52 @@ 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
if ((p->quirks & QuirkSWRender) == 0)
- p->UninitStagefrightSurface();
+ p->ReleaseSurfaceTexture();
#if defined(DEBUG_VERBOSE)
CLog::Log(LOGDEBUG, "Final Cleaning\n", p->in_queue.size());
#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)
@@ -870,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();
}
@@ -906,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)
- {
- if ((*it).first == eglimg)
- break;
- }
- if (it == p->free_queue.end())
+ stSlot* slot = p->getSlot(eglimg);
+ if (!slot)
{
- 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();
}
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.h
index 4ddc310e2b..f36db6794d 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.h
@@ -24,6 +24,8 @@
#include "cores/dvdplayer/DVDStreamInfo.h"
#include "DVDVideoCodec.h"
+class CApplication;
+class CApplicationMessenger;
class CWinSystemEGL;
class CAdvancedSettings;
class CStageFrightVideoPrivate;
@@ -33,11 +35,11 @@ namespace android { class MediaBuffer; }
class CStageFrightVideo
{
public:
- CStageFrightVideo(CWinSystemEGL* windowing, CAdvancedSettings* advsettings);
+ CStageFrightVideo(CApplication* application, CApplicationMessenger* applicationMessenger, CWinSystemEGL* windowing, CAdvancedSettings* advsettings);
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);
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.cpp
index ab638a099e..0390233df7 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.cpp
@@ -28,9 +28,12 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include "windowing/egl/EGLWrapper.h"
+#include "Application.h"
+#include "ApplicationMessenger.h"
#include "windowing/WindowingFactory.h"
#include "settings/AdvancedSettings.h"
#include "utils/log.h"
+#include "threads/Thread.h"
#include "android/jni/Surface.h"
#include "android/jni/SurfaceTexture.h"
@@ -102,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];
}
@@ -116,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)
@@ -268,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);
@@ -280,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);
@@ -295,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);
@@ -303,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)
@@ -318,48 +338,81 @@ void CStageFrightVideoPrivate::UninitializeEGL()
eglInitialized = false;
}
-bool CStageFrightVideoPrivate::InitStagefrightSurface()
+void CStageFrightVideoPrivate::CallbackInitSurfaceTexture(void *userdata)
+{
+ CStageFrightVideoPrivate *ctx = static_cast<CStageFrightVideoPrivate*>(userdata);
+ ctx->InitSurfaceTexture();
+}
+
+bool CStageFrightVideoPrivate::InitSurfaceTexture()
{
#if defined(DEBUG_VERBOSE)
- CLog::Log(LOGDEBUG, "%s: >>> InitStagefrightSurface\n", CLASSNAME);
+ CLog::Log(LOGDEBUG, "%s: >>> InitSurfaceTexture\n", CLASSNAME);
#endif
if (mVideoNativeWindow != NULL)
- return true;
+ return false;
mVideoTextureId = -1;
- glGenTextures(1, &mVideoTextureId);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, mVideoTextureId);
- glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+ // We MUST create the GLES texture on the main thread
+ // to match where the valid GLES context is located.
+ // It would be nice to move this out of here, we would need
+ // to create/fetch/create from g_RenderMananger. But g_RenderMananger
+ // does not know we are using MediaCodec until Configure and we
+ // we need m_surfaceTexture valid before then. Chicken, meet Egg.
+ if (m_g_application->IsCurrentThread())
+ {
+ // localize GLuint so we do not spew gles includes in our header
+ GLuint texture_id;
+
+ glGenTextures(1, &texture_id);
+ glBindTexture( GL_TEXTURE_EXTERNAL_OES, texture_id);
+ glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glBindTexture( GL_TEXTURE_EXTERNAL_OES, 0);
+ mVideoTextureId = texture_id;
+ }
+ else
+ {
+ ThreadMessageCallback callbackData;
+ callbackData.callback = &CallbackInitSurfaceTexture;
+ callbackData.userptr = (void*)this;
- mSurfTexture = new CJNISurfaceTexture(mVideoTextureId);
- mSurface = new CJNISurface(*mSurfTexture);
+ ThreadMessage msg;
+ msg.dwMessage = TMSG_CALLBACK;
+ msg.lpVoid = (void*)&callbackData;
- JNIEnv* env = xbmc_jnienv();
- mVideoNativeWindow = ANativeWindow_fromSurface(env, mSurface->get_raw());
- native_window_api_connect(mVideoNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
+ // wait for it.
+ m_g_applicationMessenger->SendMessage(msg, true);
-#if defined(DEBUG_VERBOSE)
- CLog::Log(LOGDEBUG, "%s: <<< InitStagefrightSurface\n", CLASSNAME);
-#endif
- return 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);
}
-void CStageFrightVideoPrivate::UninitStagefrightSurface()
+void CStageFrightVideoPrivate::ReleaseSurfaceTexture()
{
#if defined(DEBUG_VERBOSE)
- CLog::Log(LOGDEBUG, "%s: >>> UninitStagefrightSurface\n", CLASSNAME);
+ CLog::Log(LOGDEBUG, "%s: >>> ReleaseSurfaceTexture\n", CLASSNAME);
#endif
if (mVideoNativeWindow == NULL)
return;
native_window_api_disconnect(mVideoNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
ANativeWindow_release(mVideoNativeWindow.get());
- mVideoNativeWindow = NULL;
+ mVideoNativeWindow.clear();
mSurface->release();
mSurfTexture->release();
@@ -367,18 +420,19 @@ void CStageFrightVideoPrivate::UninitStagefrightSurface()
delete mSurface;
delete mSurfTexture;
- glDeleteTextures(1, &mVideoTextureId);
+ if (mVideoTextureId > 0)
+ glDeleteTextures(1, &mVideoTextureId);
#if defined(DEBUG_VERBOSE)
- CLog::Log(LOGDEBUG, "%s: <<< UninitStagefrightSurface\n", CLASSNAME);
+ CLog::Log(LOGDEBUG, "%s: <<< ReleaseSurfaceTexture\n", CLASSNAME);
#endif
}
-void CStageFrightVideoPrivate::UpdateStagefrightTexture()
+void CStageFrightVideoPrivate::UpdateSurfaceTexture()
{
mSurfTexture->updateTexImage();
}
-void CStageFrightVideoPrivate::GetStagefrightTransformMatrix(float* transformMatrix)
+void CStageFrightVideoPrivate::GetSurfaceTextureTransformMatrix(float* transformMatrix)
{
mSurfTexture->getTransformMatrix(transformMatrix);
}
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.h
index d10ef41354..34e9c50ffb 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.h
@@ -56,13 +56,16 @@ class CJNISurface;
class CJNISurfaceTexture;
class CWinSystemEGL;
class CAdvancedSettings;
+class CApplication;
+class CApplicationMessenger;
using namespace android;
-struct tex_slot
+struct stSlot
{
GLuint texid;
EGLImageKHR eglimg;
+ int use_cnt;
};
struct Frame
@@ -91,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;
@@ -109,6 +115,8 @@ public:
GLint mTexSamplerHandle;
GLint mTexMatrixHandle;
+ CApplication* m_g_application;
+ CApplicationMessenger* m_g_applicationMessenger;
CWinSystemEGL* m_g_Windowing;
CAdvancedSettings* m_g_advancedSettings;
@@ -118,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;
@@ -158,8 +164,9 @@ public:
CJNISurface* mSurface;
sp<ANativeWindow> mVideoNativeWindow;
- bool InitStagefrightSurface();
- void UninitStagefrightSurface();
- void UpdateStagefrightTexture();
- void GetStagefrightTransformMatrix(float* transformMatrix);
+ static void CallbackInitSurfaceTexture(void*);
+ bool InitSurfaceTexture();
+ void ReleaseSurfaceTexture();
+ void UpdateSurfaceTexture();
+ void GetSurfaceTextureTransformMatrix(float* transformMatrix);
};