diff options
author | Chris Browet <koying@semperpax.com> | 2013-11-16 12:50:10 -0800 |
---|---|---|
committer | Chris Browet <koying@semperpax.com> | 2013-11-16 12:50:10 -0800 |
commit | 06e6fb22594c91733dd2141ca8ae221fa8481101 (patch) | |
tree | 343bfc21bc5680df66bcda7ea73b2f5a4a8633e0 | |
parent | 3540cc97b3b003fde5ab9a1cbbe91788f64f345d (diff) | |
parent | 60f2fb151a21ca750a16695c313c26030c796665 (diff) |
Merge pull request #3657 from koying/quickpr
Stagefright fixes
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); }; |