From 6a234d2d973d3bd711ccdd2e1f4c4df91b9a4a73 Mon Sep 17 00:00:00 2001 From: "Chris \"koying\" Browet" Date: Mon, 28 Jan 2013 20:01:17 +0100 Subject: [PATCH] [stagefright] pre-allocate input buffers and use CThread --- addons/skin.touched | 2 +- .../Video/DVDVideoCodecStageFright.cpp | 8 + .../DVDCodecs/Video/StageFrightVideo.cpp | 733 ++++++++++-------- 3 files changed, 427 insertions(+), 316 deletions(-) diff --git a/addons/skin.touched b/addons/skin.touched index 932a728725889..1d03746646111 160000 --- a/addons/skin.touched +++ b/addons/skin.touched @@ -1 +1 @@ -Subproject commit 932a728725889c4220bc4ac42f18b082e4361f86 +Subproject commit 1d03746646111f97e28b807a290bd762c7db547c diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecStageFright.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecStageFright.cpp index 0afd2d1e8b538..69fe3565bb33e 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecStageFright.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecStageFright.cpp @@ -18,6 +18,8 @@ * */ +//#define DEBUG_VERBOSE 1 + #if (defined HAVE_CONFIG_H) && (!defined WIN32) #include "config.h" #elif defined(_WIN32) @@ -137,6 +139,9 @@ void CDVDVideoCodecStageFright::SetDropState(bool bDrop) int CDVDVideoCodecStageFright::Decode(BYTE* pData, int iSize, double dts, double pts) { +#if defined(DEBUG_VERBOSE) + unsigned int time = XbmcThreads::SystemClockMillis(); +#endif int rtn; int demuxer_bytes = iSize; uint8_t *demuxer_content = pData; @@ -152,6 +157,9 @@ int CDVDVideoCodecStageFright::Decode(BYTE* pData, int iSize, double dts, double else CLog::Log(LOGERROR,"%s::%s - bitstream_convert error", CLASSNAME, __func__); } +#if defined(DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, ">>> decode conversion - tm:%d\n", XbmcThreads::SystemClockMillis() - time); +#endif rtn = m_stf_decoder->Decode(demuxer_content, demuxer_bytes, dts, pts); diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideo.cpp index b77989196b803..8a82e09fd8b40 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideo.cpp @@ -19,7 +19,7 @@ */ /***************************************************************************/ -//#define STAGEFRIGHT_DEBUG_VERBOSE 1 +//#define DEBUG_VERBOSE 1 #include "system.h" #include "system_gl.h" @@ -29,9 +29,10 @@ #include "android/activity/XBMCApp.h" #include "guilib/GraphicContext.h" #include "DVDClock.h" -#include "threads/Event.h" #include "utils/log.h" #include "utils/fastmemcpy.h" +#include "threads/Thread.h" +#include "threads/Event.h" #include "xbmc/guilib/FrameBufferObject.h" #include "windowing/WindowingFactory.h" @@ -56,8 +57,7 @@ #define OMX_QCOM_COLOR_FormatYVU420SemiPlanar 0x7FA30C00 #define CLASSNAME "CStageFrightVideo" -#define MINBUFIN 10 -#define MAXBUFIN 25 +#define INBUFCOUNT 2 #define NUMFBOTEX 4 // EGL extension functions @@ -105,17 +105,19 @@ struct Frame MediaBuffer* medbuf; }; +class CStageFrightDecodeThread; + class CStageFrightVideoPrivate : public MediaBufferObserver { public: CStageFrightVideoPrivate() - : thread_exited(0), stop_decode(0) - , source(NULL), natwin(NULL) + : decode_thread(NULL), source(NULL), natwin(NULL) , eglDisplay(EGL_NO_DISPLAY), eglSurface(EGL_NO_SURFACE), eglContext(EGL_NO_CONTEXT) , eglInitialized(false) , mDataSize(0), mTimeSize(0), mPrevPts(-1) , cur_frame(NULL), prev_frame(NULL) , width(-1), height(-1) + , texwidth(-1), texheight(-1) , client(NULL), decoder(NULL), decoder_component(NULL) , drop_state(false), resetting(false) {} @@ -123,23 +125,36 @@ class CStageFrightVideoPrivate : public MediaBufferObserver virtual void signalBufferReturned(MediaBuffer *buffer) { mDataSize -= buffer->size(); - buffer->setObserver(NULL); - buffer->release(); } MediaBuffer* getBuffer(size_t size) { - MediaBuffer* buf = new MediaBuffer(size); - buf->setObserver(this); - buf->add_ref(); + int i=0; + for (; irefcount() == 0) + break; + if (i == INBUFCOUNT) + return NULL; + inbuf[i]->add_ref(); + inbuf[i]->set_range(0, size); mDataSize += size; - return buf; + return inbuf[i]; } + bool inputBufferAvailable() + { + for (int i=0; irefcount() == 0) + return true; + + return false; + } void loadOESShader(GLenum shaderType, const char* pSource, GLuint* outShader) { + #if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, ">>loadOESShader\n"); + #endif GLuint shader = glCreateShader(shaderType); CheckGlError("loadOESShader"); @@ -175,7 +190,9 @@ class CStageFrightVideoPrivate : public MediaBufferObserver void createOESProgram(const char* pVertexSource, const char* pFragmentSource, GLuint* outPgm) { + #if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, ">>createOESProgram\n"); + #endif GLuint vertexShader, fragmentShader; { loadOESShader(GL_VERTEX_SHADER, pVertexSource, &vertexShader); @@ -234,7 +251,9 @@ class CStageFrightVideoPrivate : public MediaBufferObserver "}\n"; { + #if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, ">>OES_shader_setUp\n"); + #endif CheckGlError("OES_shader_setUp"); createOESProgram(vsrc, fsrc, &mPgm); } @@ -243,11 +262,104 @@ class CStageFrightVideoPrivate : public MediaBufferObserver mTexSamplerHandle = glGetUniformLocation(mPgm, "texSampler"); mTexMatrixHandle = glGetUniformLocation(mPgm, "texMatrix"); } - pthread_t decode_thread_id; - volatile sig_atomic_t thread_exited, stop_decode; + + int NP2( unsigned x ) { + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return ++x; + } + + void InitializeEGL(int w, int h) + { + texwidth = w; + texheight = h; + if (!g_Windowing.IsExtSupported("GL_TEXTURE_NPOT")) + { + texwidth = NP2(texwidth); + texheight = NP2(texheight); + } + + eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + eglBindAPI(EGL_OPENGL_ES_API); + EGLint contextAttributes[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + eglContext = eglCreateContext(eglDisplay, g_Windowing.GetEGLConfig(), EGL_NO_CONTEXT, contextAttributes); + EGLint pbufferAttribs[] = { + EGL_WIDTH, texwidth, + EGL_HEIGHT, texheight, + EGL_NONE + }; + eglSurface = eglCreatePbufferSurface(eglDisplay, g_Windowing.GetEGLConfig(), pbufferAttribs); + eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); + CheckGlError("stf init"); + + static const EGLint imageAttributes[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_FALSE, + EGL_GL_TEXTURE_LEVEL_KHR, 0, + EGL_NONE + }; + + for (int i=0; i(slots[i].eglimg, i)); + + } + glBindTexture(GL_TEXTURE_2D, 0); + + fbo.Initialize(); + OES_shader_setUp(); + + eglInitialized = true; +#if defined(DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s: >>> Initialized EGL: w:%d; h:%d\n", CLASSNAME, texwidth, texheight); +#endif + } + + void UninitializeEGL() + { + fbo.Cleanup(); + for (int i=0; i source; sp natwin; + + MediaBuffer* inbuf[INBUFCOUNT]; GLuint mPgm; GLint mPositionHandle; @@ -286,6 +398,7 @@ class CStageFrightVideoPrivate : public MediaBufferObserver bool source_done; int x, y; int width, height; + int texwidth, texheight; OMXClient *client; sp decoder; @@ -296,13 +409,185 @@ class CStageFrightVideoPrivate : public MediaBufferObserver bool drop_state; bool resetting; -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) +#if defined(DEBUG_VERBOSE) unsigned int cycle_time; #endif }; /********************************************/ +class CStageFrightDecodeThread : public CThread +{ +protected: + CStageFrightVideoPrivate *p; + +public: + CStageFrightDecodeThread(CStageFrightVideoPrivate *priv) + : CThread("CStageFrightDecodeThread") + , p(priv) + {} + + void OnStartup() + { + #if defined(DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s: entering decode thread\n", CLASSNAME); + #endif + } + + void OnExit() + { + #if defined(DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s: exited decode thread\n", CLASSNAME); + #endif + } + + void Process() + { + Frame* frame; + int32_t w, h, dw, dh; + int decode_done = 0; + int32_t keyframe = 0; + int32_t unreadable = 0; + MediaSource::ReadOptions readopt; + + do + { + #if defined(DEBUG_VERBOSE) + unsigned int time = XbmcThreads::SystemClockMillis(); + CLog::Log(LOGDEBUG, "%s: >>> Handling frame\n", CLASSNAME); + #endif + p->cur_frame = NULL; + frame = (Frame*)malloc(sizeof(Frame)); + if (!frame) + { + frame->status = VC_ERROR; + decode_done = 1; + continue; + } + + frame->medbuf = NULL; + if (p->resetting) + { + readopt.setSeekTo(0); + p->resetting = false; + } + frame->status = p->decoder->read(&frame->medbuf, &readopt); + readopt.clearSeekTo(); + if (frame->status == OK) + { + if (!frame->medbuf->graphicBuffer().get()) // hw buffers + { + if (frame->medbuf->range_length() == 0) + { + CLog::Log(LOGERROR, "%s - Invalid buffer\n", CLASSNAME); + frame->status = VC_ERROR; + decode_done = 1; + frame->medbuf->release(); + frame->medbuf = NULL; + } + else + frame->format = RENDER_FMT_YUV420P; + } + else + frame->format = RENDER_FMT_EGLIMG; + + sp outFormat = p->decoder->getFormat(); + outFormat->findInt32(kKeyWidth , &w); + outFormat->findInt32(kKeyHeight, &h); + + if (!outFormat->findInt32(kKeyDisplayWidth , &dw)) + dw = w; + if (!outFormat->findInt32(kKeyDisplayHeight, &dh)) + dh = h; + + if (!outFormat->findInt32(kKeyIsSyncFrame, &keyframe)) + keyframe = 0; + if (!outFormat->findInt32(kKeyIsUnreadable, &unreadable)) + unreadable = 0; + + frame->pts = 0; + + // The OMX.SEC decoder doesn't signal the modified width/height + if (p->decoder_component && !strncmp(p->decoder_component, "OMX.SEC", 7) && + (w & 15 || h & 15)) + { + 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) + { + int32_t cropLeft, cropTop, cropRight, cropBottom; + sp outFormat = p->decoder->getFormat(); + + outFormat->findInt32(kKeyWidth , &p->width); + outFormat->findInt32(kKeyHeight, &p->height); + + if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) + { + p->x = 0; + p->y = 0; + } + else + { + p->x = cropLeft; + p->y = cropTop; + p->width = cropRight - cropLeft + 1; + p->height = cropBottom - cropTop + 1; + } + outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat); + if (!outFormat->findInt32(kKeyStride, &p->videoStride)) + p->videoStride = p->width; + if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight)) + p->videoSliceHeight = p->height; + + if (frame->medbuf) + frame->medbuf->release(); + frame->medbuf = NULL; + continue; + } + else + { + CLog::Log(LOGERROR, "%s - decoding error (%d)\n", CLASSNAME,frame->status); + decode_done = 1; + if (frame->medbuf) + frame->medbuf->release(); + frame->medbuf = NULL; + } + + if (frame->status == OK && frame->format == RENDER_FMT_EGLIMG) + { + android::GraphicBuffer* graphicBuffer = static_cast(frame->medbuf->graphicBuffer().get() ); + native_window_set_buffers_timestamp(p->natwin.get(), frame->pts * 1000); + int err = p->natwin.get()->queueBuffer(p->natwin.get(), graphicBuffer); + if (err == 0) + frame->medbuf->meta_data()->setInt32(kKeyRendered, 1); + frame->medbuf->release(); + frame->medbuf = NULL; + } + + #if defined(DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s: >>> pushed OUT frame; w:%d, h:%d, dw:%d, dh:%d, kf:%d, ur:%d, tm:%d\n", CLASSNAME, w, h, dw, dh, keyframe, unreadable, XbmcThreads::SystemClockMillis() - time); + #endif + + pthread_mutex_lock(&p->out_mutex); + p->cur_frame = frame; + while (p->cur_frame) + pthread_cond_wait(&p->out_condition, &p->out_mutex); + pthread_mutex_unlock(&p->out_mutex); + } + while (!decode_done && !m_bStop); + } +}; + +/***********************************************************/ + class CustomSource : public MediaSource { public: @@ -333,13 +618,24 @@ class CustomSource : public MediaSource Frame *frame; status_t ret; *buffer = NULL; - -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) - CLog::Log(LOGDEBUG, "%s: reading source(%d)\n", CLASSNAME,p->in_queue.size()); + int64_t time_us = -1; + MediaSource::ReadOptions::SeekMode mode; + + if (options && options->getSeekTo(&time_us, &mode)) + { +#if defined(DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s: reading source(%d): seek:%llu\n", CLASSNAME,p->in_queue.size(), time_us); +#endif + } + else + { +#if defined(DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s: reading source(%d)\n", CLASSNAME,p->in_queue.size()); #endif + } pthread_mutex_lock(&p->in_mutex); - while (p->in_queue.empty() && !p->stop_decode) + while (p->in_queue.empty() && p->decode_thread) pthread_cond_wait(&p->in_condition, &p->in_mutex); if (p->in_queue.empty()) @@ -350,19 +646,16 @@ class CustomSource : public MediaSource frame = *p->in_queue.begin(); ret = frame->status; - - if (ret == OK) - *buffer = frame->medbuf->clone(); + *buffer = frame->medbuf; p->in_queue.erase(p->in_queue.begin()); p->mTimeSize -= frame->duration; pthread_mutex_unlock(&p->in_mutex); -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) +#if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, ">>> exiting reading source(%d); pts:%llu\n", p->in_queue.size(),frame->pts); #endif - frame->medbuf->release(); free(frame); return ret; @@ -375,167 +668,9 @@ class CustomSource : public MediaSource /***********************************************************/ -void* decode_thread(void *arg) -{ -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) - unsigned int time; - CLog::Log(LOGDEBUG, "%s: entering decode thread\n", CLASSNAME); -#endif - - CStageFrightVideoPrivate *p = (CStageFrightVideoPrivate*)arg; - Frame* frame; - int32_t w, h, dw, dh; - int decode_done = 0; - int32_t keyframe = 0; - int32_t unreadable = 0; - MediaSource::ReadOptions readopt; - - - do - { - #if defined(STAGEFRIGHT_DEBUG_VERBOSE) - time = XbmcThreads::SystemClockMillis(); - CLog::Log(LOGDEBUG, "%s: >>> Handling frame\n", CLASSNAME); - #endif - p->cur_frame = NULL; - frame = (Frame*)malloc(sizeof(Frame)); - if (!frame) - { - frame->status = VC_ERROR; - decode_done = 1; - continue; - } - - frame->medbuf = NULL; - if (p->resetting) - { - readopt.setSeekTo(0); - p->resetting = false; - } - frame->status = p->decoder->read(&frame->medbuf, &readopt); - readopt.clearSeekTo(); - if (frame->status == OK) - { - if (!frame->medbuf->graphicBuffer().get()) // hw buffers - { - if (frame->medbuf->range_length() == 0) - { - CLog::Log(LOGERROR, "%s - Invalid buffer\n", CLASSNAME); - frame->status = VC_ERROR; - decode_done = 1; - frame->medbuf->release(); - frame->medbuf = NULL; - } - else - frame->format = RENDER_FMT_YUV420P; - } - else - frame->format = RENDER_FMT_EGLIMG; - - sp outFormat = p->decoder->getFormat(); - outFormat->findInt32(kKeyWidth , &w); - outFormat->findInt32(kKeyHeight, &h); - - if (!outFormat->findInt32(kKeyDisplayWidth , &dw)) - dw = w; - if (!outFormat->findInt32(kKeyDisplayHeight, &dh)) - dh = h; - - if (!outFormat->findInt32(kKeyIsSyncFrame, &keyframe)) - keyframe = 0; - if (!outFormat->findInt32(kKeyIsUnreadable, &unreadable)) - unreadable = 0; - - frame->pts = 0; - - // The OMX.SEC decoder doesn't signal the modified width/height - if (p->decoder_component && !strncmp(p->decoder_component, "OMX.SEC", 7) && - (w & 15 || h & 15)) - { - 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) - { - int32_t cropLeft, cropTop, cropRight, cropBottom; - sp outFormat = p->decoder->getFormat(); - - if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) - { - p->x = 0; - p->y = 0; - } - else - { - p->x = cropLeft; - p->y = cropTop; - p->width = cropRight - cropLeft + 1; - p->height = cropBottom - cropTop + 1; - } - outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat); - if (!outFormat->findInt32(kKeyStride, &p->videoStride)) - p->videoStride = p->width; - if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight)) - p->videoSliceHeight = p->height; - - if (frame->medbuf) - frame->medbuf->release(); - frame->medbuf = NULL; - continue; - } - else - { - CLog::Log(LOGERROR, "%s - decoding error (%d)\n", CLASSNAME,frame->status); - decode_done = 1; - if (frame->medbuf) - frame->medbuf->release(); - frame->medbuf = NULL; - } - - #if defined(STAGEFRIGHT_DEBUG_VERBOSE) - CLog::Log(LOGDEBUG, "%s: >>> pushed OUT frame; w:%d, h:%d, dw:%d, dh:%d, kf:%d, ur:%d, tm:%d\n", CLASSNAME, w, h, dw, dh, keyframe, unreadable, XbmcThreads::SystemClockMillis() - time); - #endif - - if (frame->status == OK && frame->format == RENDER_FMT_EGLIMG) - { - android::GraphicBuffer* graphicBuffer = static_cast(frame->medbuf->graphicBuffer().get() ); - native_window_set_buffers_timestamp(p->natwin.get(), frame->pts * 1000); - int err = p->natwin.get()->queueBuffer(p->natwin.get(), graphicBuffer); - if (err == 0) - frame->medbuf->meta_data()->setInt32(kKeyRendered, 1); - frame->medbuf->release(); - frame->medbuf = NULL; - } - - pthread_mutex_lock(&p->out_mutex); - p->cur_frame = frame; - while (p->cur_frame) - pthread_cond_wait(&p->out_condition, &p->out_mutex); - pthread_mutex_unlock(&p->out_mutex); - } - while (!decode_done && !p->stop_decode); - -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) - unsigned int time; - CLog::Log(LOGDEBUG, "%s: exited decode thread\n", CLASSNAME); -#endif - p->thread_exited = 1; - - return 0; -} - -/***********************************************************/ - bool CStageFrightVideo::Open(CDVDStreamInfo &hints) { -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) +#if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, "%s::Open\n", CLASSNAME); #endif @@ -630,16 +765,6 @@ bool CStageFrightVideo::Open(CDVDStreamInfo &hints) goto fail; } - if (!outFormat->findInt32(kKeyStride, &p->videoStride)) - p->videoStride = p->width; - if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight)) - p->videoSliceHeight = p->height; - - const char *component; - if (outFormat->findCString(kKeyDecoderComponent, &component)) - CLog::Log(LOGDEBUG, "%s::%s - component: %s\n", CLASSNAME, __func__, component); - - if (!outFormat->findInt32(kKeyStride, &p->videoStride)) p->videoStride = p->width; if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight)) @@ -658,13 +783,24 @@ bool CStageFrightVideo::Open(CDVDStreamInfo &hints) p->height = cropBottom - cropTop + 1; } + for (int i=0; iinbuf[i] = new MediaBuffer((p->width * p->height) *3 /2); + p->inbuf[i]->setObserver(p); + } + + const char *component; + if (outFormat->findCString(kKeyDecoderComponent, &component)) + CLog::Log(LOGDEBUG, "%s::%s - component: %s\n", CLASSNAME, __func__, component); + pthread_mutex_init(&p->in_mutex, NULL); pthread_cond_init(&p->in_condition, NULL); pthread_mutex_init(&p->out_mutex, NULL); pthread_cond_init(&p->out_condition, NULL); pthread_mutex_init(&p->free_mutex, NULL); - pthread_create(&(p->decode_thread_id), NULL, &decode_thread, p); + p->decode_thread = new CStageFrightDecodeThread(p); + p->decode_thread->Create(true /*autodelete*/); p->client->disconnect(); @@ -692,71 +828,15 @@ bool CStageFrightVideo::Open(CDVDStreamInfo &hints) /*** Decode ***/ int CStageFrightVideo::Decode(BYTE *pData, int iSize, double dts, double pts) { -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) +#if defined(DEBUG_VERBOSE) unsigned int time = XbmcThreads::SystemClockMillis(); CLog::Log(LOGDEBUG, "%s::Decode - d:%p; s:%d; dts:%f; pts:%f\n", CLASSNAME, pData, iSize, dts, pts); - if (p->cycle_time != 0) - CLog::Log(LOGDEBUG, ">>> cycle dur:%d\n", XbmcThreads::SystemClockMillis() - p->cycle_time); - p->cycle_time = time; #endif Frame *frame; int demuxer_bytes = iSize; uint8_t *demuxer_content = pData; - if (!p->eglInitialized) - { - p->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglBindAPI(EGL_OPENGL_ES_API); - EGLint contextAttributes[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - p->eglContext = eglCreateContext(p->eglDisplay, g_Windowing.GetEGLConfig(), EGL_NO_CONTEXT, contextAttributes); - EGLint pbufferAttribs[] = { - EGL_WIDTH, p->width, - EGL_HEIGHT, p->height, - EGL_NONE - }; - p->eglSurface = eglCreatePbufferSurface(p->eglDisplay, g_Windowing.GetEGLConfig(), pbufferAttribs); - eglMakeCurrent(p->eglDisplay, p->eglSurface, p->eglSurface, p->eglContext); - CheckGlError("stf init"); - - static const EGLint imageAttributes[] = { - EGL_IMAGE_PRESERVED_KHR, EGL_FALSE, - EGL_GL_TEXTURE_LEVEL_KHR, 0, - EGL_NONE - }; - - for (int i=0; islots[i].texid)); - glBindTexture(GL_TEXTURE_2D, p->slots[i].texid); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p->width, p->height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, 0); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - // This is necessary for non-power-of-two textures - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - p->slots[i].eglimg = eglCreateImageKHR(p->eglDisplay, p->eglContext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(p->slots[i].texid),imageAttributes); - p->free_queue.push_back(std::pair(p->slots[i].eglimg, i)); - - } - glBindTexture(GL_TEXTURE_2D, 0); - - p->fbo.Initialize(); - p->OES_shader_setUp(); - - p->eglInitialized = true; - } - - if (p->free_queue.empty()) - return VC_ERROR; - if (demuxer_content) { frame = (Frame*)malloc(sizeof(Frame)); @@ -782,32 +862,23 @@ int CStageFrightVideo::Decode(BYTE *pData, int iSize, double dts, double pts) frame->duration = frame->pts - p->mPrevPts; p->mTimeSize += frame->duration; } - p->mPrevPts = frame->pts; + if (frame->pts > 0) + p->mPrevPts = frame->pts; - while (true) { - if (p->thread_exited) { - p->source_done = true; - break; - } - pthread_mutex_lock(&p->in_mutex); - if (p->in_queue.size() >= MAXBUFIN && p->cur_frame == NULL) { - pthread_mutex_unlock(&p->in_mutex); - usleep(1000); - continue; - } - p->in_queue.push_back(frame); - pthread_cond_signal(&p->in_condition); - pthread_mutex_unlock(&p->in_mutex); - break; - } + pthread_mutex_lock(&p->in_mutex); + p->in_queue.push_back(frame); + pthread_cond_signal(&p->in_condition); + pthread_mutex_unlock(&p->in_mutex); } - int ret = VC_BUFFER; - pthread_mutex_lock(&p->in_mutex); - if (p->cur_frame != NULL && p->in_queue.size() >= MINBUFIN) + int ret = 0; + if (p->inputBufferAvailable()) + ret |= VC_BUFFER; + else + usleep(1000); + if (p->cur_frame != NULL) ret |= VC_PICTURE; - pthread_mutex_unlock(&p->in_mutex); -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) +#if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, "%s::Decode: pushed IN frame (%d); tm:%d\n", CLASSNAME,p->in_queue.size(), XbmcThreads::SystemClockMillis() - time); #endif @@ -816,7 +887,7 @@ int CStageFrightVideo::Decode(BYTE *pData, int iSize, double dts, double pts) bool CStageFrightVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture) { - #if defined(STAGEFRIGHT_DEBUG_VERBOSE) + #if defined(DEBUG_VERBOSE) unsigned int time = XbmcThreads::SystemClockMillis(); #endif if (p->prev_frame) { @@ -825,7 +896,7 @@ bool CStageFrightVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture) free(p->prev_frame); p->prev_frame = NULL; } -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) +#if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, "%s::ClearPicture (%d)\n", CLASSNAME, XbmcThreads::SystemClockMillis() - time); #endif @@ -834,9 +905,12 @@ bool CStageFrightVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture) bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) { -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) +#if defined(DEBUG_VERBOSE) unsigned int time = XbmcThreads::SystemClockMillis(); CLog::Log(LOGDEBUG, "%s::GetPicture\n", CLASSNAME); + if (p->cycle_time != 0) + CLog::Log(LOGDEBUG, ">>> cycle dur:%d\n", XbmcThreads::SystemClockMillis() - p->cycle_time); + p->cycle_time = time; #endif status_t status; @@ -853,6 +927,18 @@ bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) Frame *frame = p->cur_frame; status = frame->status; + pDvdVideoPicture->format = frame->format; + pDvdVideoPicture->pts = DVD_NOPTS_VALUE; + pDvdVideoPicture->dts = DVD_NOPTS_VALUE; + pDvdVideoPicture->pts = frame->pts; + pDvdVideoPicture->iWidth = frame->width; + pDvdVideoPicture->iHeight = frame->height; + pDvdVideoPicture->iDisplayWidth = frame->width; + pDvdVideoPicture->iDisplayHeight = frame->height; + pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; + pDvdVideoPicture->stf = this; + pDvdVideoPicture->eglimg = EGL_NO_IMAGE_KHR; + if (status != OK) { CLog::Log(LOGERROR, "%s::%s - Error getting picture from frame(%d)\n", CLASSNAME, __func__,status); @@ -866,19 +952,31 @@ bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) return false; } - pDvdVideoPicture->format = frame->format; - pDvdVideoPicture->pts = frame->pts; - pDvdVideoPicture->dts = DVD_NOPTS_VALUE; - pDvdVideoPicture->iWidth = frame->width; - pDvdVideoPicture->iHeight = frame->height; - pDvdVideoPicture->iDisplayWidth = frame->width; - pDvdVideoPicture->iDisplayHeight = frame->height; - pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; - pDvdVideoPicture->stf = this; - pDvdVideoPicture->eglimg = EGL_NO_IMAGE_KHR; - if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG) { + if (!p->eglInitialized) + { + p->InitializeEGL(frame->width, frame->height); + } + else if (p->texwidth != frame->width || p->texheight != frame->height) + { + p->UninitializeEGL(); + 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); + p->cur_frame = NULL; + pthread_cond_signal(&p->out_condition); + pthread_mutex_unlock(&p->out_mutex); + return false; + } + g_xbmcapp.UpdateStagefrightTexture(); if (!p->drop_state) @@ -920,7 +1018,7 @@ bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) pDvdVideoPicture->eglimg = p->slots[cur_slot].eglimg; glBindTexture(GL_TEXTURE_2D, 0); - #if defined(STAGEFRIGHT_DEBUG_VERBOSE) + #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 } @@ -960,7 +1058,7 @@ bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) default: CLog::Log(LOGERROR, "%s::%s - Unsupported color format(%d)\n", CLASSNAME, __func__,p->videoColorFormat); } - #if defined(STAGEFRIGHT_DEBUG_VERBOSE) + #if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, ">>> pic pts:%f, data:%p, col:%d, w:%d, h:%d, tm:%d\n", pDvdVideoPicture->pts, data, p->videoColorFormat, p->videoStride, p->videoSliceHeight, XbmcThreads::SystemClockMillis() - time); #endif } @@ -978,18 +1076,23 @@ bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) void CStageFrightVideo::Close() { -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) +#if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, "%s::Close\n", CLASSNAME); #endif Frame *frame; - p->stop_decode = 1; + if (p->decode_thread && p->decode_thread->IsRunning()) + p->decode_thread->StopThread(false); + p->decode_thread = NULL; pthread_cond_signal(&p->in_condition); // Give decoder_thread time to process EOS, if stuck on reading usleep(50000); +#if defined(DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "Cleaning OUT\n"); +#endif pthread_mutex_lock(&p->out_mutex); if (p->cur_frame) { @@ -1009,12 +1112,13 @@ void CStageFrightVideo::Close() p->prev_frame = NULL; } +#if defined(DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "Stopping omxcodec\n"); +#endif p->decoder->stop(); p->client->disconnect(); - pthread_join(p->decode_thread_id, NULL); - -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) +#if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, "Cleaning IN(%d)\n", p->in_queue.size()); #endif while (!p->in_queue.empty()) @@ -1032,33 +1136,26 @@ void CStageFrightVideo::Close() delete p->client; g_xbmcapp.UninitStagefrightSurface(); - - p->fbo.Cleanup(); - for (int i=0; islots[i].texid)); - eglDestroyImageKHR(p->eglDisplay, p->slots[i].eglimg); - } - - if (p->eglContext != EGL_NO_CONTEXT) - eglDestroyContext(p->eglDisplay, p->eglContext); - p->eglContext = EGL_NO_CONTEXT; - - if (p->eglSurface != EGL_NO_SURFACE) - eglDestroySurface(p->eglDisplay, p->eglSurface); - p->eglSurface = EGL_NO_SURFACE; + p->UninitializeEGL(); pthread_mutex_destroy(&p->in_mutex); pthread_cond_destroy(&p->in_condition); pthread_mutex_destroy(&p->out_mutex); pthread_cond_destroy(&p->out_condition); pthread_mutex_destroy(&p->free_mutex); + + for (int i=0; iinbuf[i]->setObserver(NULL); + p->inbuf[i]->release(); + } + delete p; } void CStageFrightVideo::Reset(void) { -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) +#if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, "%s::Reset\n", CLASSNAME); #endif Frame* frame; @@ -1083,7 +1180,7 @@ void CStageFrightVideo::SetDropState(bool bDrop) if (bDrop == p->drop_state) return; -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) +#if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, "%s::SetDropState (%d->%d)\n", CLASSNAME,p->drop_state,bDrop); #endif @@ -1096,11 +1193,17 @@ void CStageFrightVideo::SetSpeed(int iSpeed) int CStageFrightVideo::GetDataSize(void) { +#if defined(DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::GetDataSize (%d)\n", CLASSNAME,p->mDataSize); +#endif return p->mDataSize; } double CStageFrightVideo::GetTimeSize(void) { +#if defined(DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::GetTimeSize (%llu)\n", CLASSNAME,p->mTimeSize); +#endif return pts_itod(p->mTimeSize); } @@ -1108,7 +1211,7 @@ double CStageFrightVideo::GetTimeSize(void) void CStageFrightVideo::LockBuffer(EGLImageKHR eglimg) { - #if defined(STAGEFRIGHT_DEBUG_VERBOSE) + #if defined(DEBUG_VERBOSE) unsigned int time = XbmcThreads::SystemClockMillis(); #endif pthread_mutex_lock(&p->free_mutex); @@ -1123,7 +1226,7 @@ void CStageFrightVideo::LockBuffer(EGLImageKHR eglimg) pthread_mutex_unlock(&p->free_mutex); return; } -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) +#if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, "Locking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time); #endif @@ -1134,7 +1237,7 @@ void CStageFrightVideo::LockBuffer(EGLImageKHR eglimg) void CStageFrightVideo::ReleaseBuffer(EGLImageKHR eglimg) { - #if defined(STAGEFRIGHT_DEBUG_VERBOSE) + #if defined(DEBUG_VERBOSE) unsigned int time = XbmcThreads::SystemClockMillis(); #endif pthread_mutex_lock(&p->free_mutex); @@ -1149,7 +1252,7 @@ void CStageFrightVideo::ReleaseBuffer(EGLImageKHR eglimg) pthread_mutex_unlock(&p->free_mutex); return; } -#if defined(STAGEFRIGHT_DEBUG_VERBOSE) +#if defined(DEBUG_VERBOSE) CLog::Log(LOGDEBUG, "Unlocking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time); #endif