2 * Copyright (C) 2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
20 /***************************************************************************/
22 //#define DEBUG_VERBOSE 1
25 #include "system_gl.h"
27 #include "StageFrightVideo.h"
28 #include "StageFrightVideoPrivate.h"
30 #include "guilib/GraphicContext.h"
32 #include "utils/log.h"
33 #include "utils/fastmemcpy.h"
34 #include "threads/Thread.h"
35 #include "threads/Event.h"
36 #include "settings/AdvancedSettings.h"
38 #include "xbmc/guilib/FrameBufferObject.h"
41 #include <EGL/eglext.h>
42 #include "windowing/egl/EGLWrapper.h"
46 #define OMX_QCOM_COLOR_FormatYVU420SemiPlanar 0x7FA30C00
47 #define OMX_TI_COLOR_FormatYUV420PackedSemiPlanar 0x7F000100
49 #define CLASSNAME "CStageFrightVideo"
51 #define EGL_NATIVE_BUFFER_ANDROID 0x3140
52 #define EGL_IMAGE_PRESERVED_KHR 0x30D2
54 const char *MEDIA_MIMETYPE_VIDEO_WMV = "video/x-ms-wmv";
56 using namespace android;
58 static int64_t pts_dtoi(double pts)
60 return (int64_t)(pts);
63 static double pts_itod(int64_t pts)
68 /***********************************************************/
70 class CStageFrightMediaSource : public MediaSource
73 CStageFrightMediaSource(CStageFrightVideoPrivate *priv, sp<MetaData> meta)
79 virtual sp<MetaData> getFormat()
84 virtual status_t start(MetaData *params)
89 virtual status_t stop()
94 virtual status_t read(MediaBuffer **buffer,
95 const MediaSource::ReadOptions *options)
100 int64_t time_us = -1;
101 MediaSource::ReadOptions::SeekMode mode;
103 if (options && options->getSeekTo(&time_us, &mode))
105 #if defined(DEBUG_VERBOSE)
106 CLog::Log(LOGDEBUG, "%s: reading source(%d): seek:%llu\n", CLASSNAME,p->in_queue.size(), time_us);
111 #if defined(DEBUG_VERBOSE)
112 CLog::Log(LOGDEBUG, "%s: reading source(%d)\n", CLASSNAME,p->in_queue.size());
117 while (p->in_queue.empty() && p->decode_thread)
118 p->in_condition.wait(p->in_mutex);
120 if (p->in_queue.empty())
122 p->in_mutex.unlock();
126 std::map<int64_t,Frame*>::iterator it = p->in_queue.begin();
129 *buffer = frame->medbuf;
131 p->in_queue.erase(it);
132 p->in_mutex.unlock();
134 #if defined(DEBUG_VERBOSE)
135 CLog::Log(LOGDEBUG, ">>> exiting reading source(%d); pts:%llu\n", p->in_queue.size(),frame->pts);
144 sp<MetaData> source_meta;
145 CStageFrightVideoPrivate *p;
148 /********************************************/
150 class CStageFrightDecodeThread : public CThread
153 CStageFrightVideoPrivate *p;
156 CStageFrightDecodeThread(CStageFrightVideoPrivate *priv)
157 : CThread("CStageFrightDecodeThread")
163 #if defined(DEBUG_VERBOSE)
164 CLog::Log(LOGDEBUG, "%s: entering decode thread\n", CLASSNAME);
170 #if defined(DEBUG_VERBOSE)
171 CLog::Log(LOGDEBUG, "%s: exited decode thread\n", CLASSNAME);
178 int32_t w, h, dw, dh;
180 int32_t keyframe = 0;
181 int32_t unreadable = 0;
182 MediaSource::ReadOptions readopt;
185 //SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
188 #if defined(DEBUG_VERBOSE)
189 unsigned int time = XbmcThreads::SystemClockMillis();
190 CLog::Log(LOGDEBUG, "%s: >>> Handling frame\n", CLASSNAME);
193 frame = (Frame*)malloc(sizeof(Frame));
200 frame->eglimg = EGL_NO_IMAGE_KHR;
201 frame->medbuf = NULL;
204 readopt.setSeekTo(0);
205 p->resetting = false;
207 frame->status = p->decoder->read(&frame->medbuf, &readopt);
208 readopt.clearSeekTo();
210 if (frame->status == OK)
212 if (!frame->medbuf->graphicBuffer().get()) // hw buffers
214 if (frame->medbuf->range_length() == 0)
216 CLog::Log(LOGERROR, "%s - Invalid buffer\n", CLASSNAME);
217 frame->status = VC_ERROR;
219 frame->medbuf->release();
220 frame->medbuf = NULL;
223 frame->format = RENDER_FMT_YUV420P;
226 frame->format = RENDER_FMT_EGLIMG;
229 if (frame->status == OK)
231 sp<MetaData> outFormat = p->decoder->getFormat();
232 outFormat->findInt32(kKeyWidth , &w);
233 outFormat->findInt32(kKeyHeight, &h);
235 if (!outFormat->findInt32(kKeyDisplayWidth , &dw))
237 if (!outFormat->findInt32(kKeyDisplayHeight, &dh))
240 if (!outFormat->findInt32(kKeyIsSyncFrame, &keyframe))
242 if (!outFormat->findInt32(kKeyIsUnreadable, &unreadable))
247 // The OMX.SEC decoder doesn't signal the modified width/height
248 if (p->decoder_component && !strncmp(p->decoder_component, "OMX.SEC", 7) &&
251 if (((w + 15)&~15) * ((h + 15)&~15) * 3/2 == frame->medbuf->range_length())
259 frame->medbuf->meta_data()->findInt64(kKeyTime, &(frame->pts));
261 else if (frame->status == INFO_FORMAT_CHANGED)
263 int32_t cropLeft, cropTop, cropRight, cropBottom;
264 sp<MetaData> outFormat = p->decoder->getFormat();
266 outFormat->findInt32(kKeyWidth , &p->width);
267 outFormat->findInt32(kKeyHeight, &p->height);
269 cropLeft = cropTop = cropRight = cropBottom = 0;
270 if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
279 p->width = cropRight - cropLeft + 1;
280 p->height = cropBottom - cropTop + 1;
282 outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat);
283 if (!outFormat->findInt32(kKeyStride, &p->videoStride))
284 p->videoStride = p->width;
285 if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
286 p->videoSliceHeight = p->height;
288 #if defined(DEBUG_VERBOSE)
289 CLog::Log(LOGDEBUG, ">>> new format col:%d, w:%d, h:%d, sw:%d, sh:%d, ctl:%d,%d; cbr:%d,%d\n", p->videoColorFormat, p->width, p->height, p->videoStride, p->videoSliceHeight, cropTop, cropLeft, cropBottom, cropRight);
293 frame->medbuf->release();
294 frame->medbuf = NULL;
300 CLog::Log(LOGERROR, "%s - decoding error (%d)\n", CLASSNAME,frame->status);
303 frame->medbuf->release();
304 frame->medbuf = NULL;
307 if (frame->format == RENDER_FMT_EGLIMG)
309 if (!p->eglInitialized)
311 p->InitializeEGL(frame->width, frame->height);
313 else if (p->texwidth != frame->width || p->texheight != frame->height)
315 p->UninitializeEGL();
316 p->InitializeEGL(frame->width, frame->height);
319 if (p->free_queue.empty())
321 CLog::Log(LOGERROR, "%s::%s - Error: No free output buffers\n", CLASSNAME, __func__);
323 frame->medbuf->release();
328 ANativeWindowBuffer* graphicBuffer = frame->medbuf->graphicBuffer()->getNativeBuffer();
329 native_window_set_buffers_timestamp(p->mVideoNativeWindow.get(), frame->pts * 1000);
330 int err = p->mVideoNativeWindow.get()->queueBuffer(p->mVideoNativeWindow.get(), graphicBuffer);
332 frame->medbuf->meta_data()->setInt32(kKeyRendered, 1);
333 frame->medbuf->release();
334 frame->medbuf = NULL;
335 p->UpdateStagefrightTexture();
339 p->free_mutex.lock();
340 while (!p->free_queue.size())
342 std::list<std::pair<EGLImageKHR, int> >::iterator itfree = p->free_queue.begin();
343 int cur_slot = itfree->second;
344 p->fbo.BindToTexture(GL_TEXTURE_2D, p->slots[cur_slot].texid);
345 p->fbo.BeginRender();
347 glDisable(GL_DEPTH_TEST);
348 //glClear(GL_COLOR_BUFFER_BIT);
350 const GLfloat triangleVertices[] = {
357 glVertexAttribPointer(p->mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);
358 glEnableVertexAttribArray(p->mPositionHandle);
360 glUseProgram(p->mPgm);
361 glUniform1i(p->mTexSamplerHandle, 0);
363 glBindTexture(GL_TEXTURE_EXTERNAL_OES, p->mVideoTextureId);
365 GLfloat texMatrix[16];
366 // const GLfloat texMatrix[] = {
372 p->GetStagefrightTransformMatrix(texMatrix);
373 glUniformMatrix4fv(p->mTexMatrixHandle, 1, GL_FALSE, texMatrix);
375 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
377 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
378 // glDeleteTextures(1, &texid);
379 // eglDestroyImageKHR(p->eglDisplay, img);
382 glBindTexture(GL_TEXTURE_2D, 0);
384 frame->eglimg = p->slots[cur_slot].eglimg;
385 p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
386 p->free_queue.erase(itfree);
387 p->free_mutex.unlock();
391 #if defined(DEBUG_VERBOSE)
392 CLog::Log(LOGDEBUG, "%s: >>> pushed OUT frame; w:%d, h:%d, dw:%d, dh:%d, kf:%d, ur:%d, img:%p, tm:%d\n", CLASSNAME, frame->width, frame->height, dw, dh, keyframe, unreadable, frame->eglimg, XbmcThreads::SystemClockMillis() - time);
396 p->cur_frame = frame;
398 p->out_condition.wait(p->out_mutex);
399 p->out_mutex.unlock();
401 while (!decode_done && !m_bStop);
403 if (p->eglInitialized)
404 p->UninitializeEGL();
409 /***********************************************************/
411 bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
413 #if defined(DEBUG_VERBOSE)
414 CLog::Log(LOGDEBUG, "%s::Open\n", CLASSNAME);
417 CSingleLock lock(g_graphicsContext);
419 // stagefright crashes with null size. Trap this...
420 if (!hints.width || !hints.height)
422 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"null size, cannot handle");
426 p = new CStageFrightVideoPrivate;
427 p->width = hints.width;
428 p->height = hints.height;
430 if (g_advancedSettings.m_stagefrightConfig.useSwRenderer)
431 p->quirks |= QuirkSWRender;
433 sp<MetaData> outFormat;
434 int32_t cropLeft, cropTop, cropRight, cropBottom;
435 //Vector<String8> matchingCodecs;
437 p->meta = new MetaData;
443 const char* mimetype;
447 if (g_advancedSettings.m_stagefrightConfig.useAVCcodec == 0)
449 mimetype = MEDIA_MIMETYPE_VIDEO_AVC;
450 if ( *(char*)hints.extradata == 1 )
451 p->meta->setData(kKeyAVCC, kTypeAVCC, hints.extradata, hints.extrasize);
454 if (g_advancedSettings.m_stagefrightConfig.useMP4codec == 0)
456 mimetype = MEDIA_MIMETYPE_VIDEO_MPEG4;
458 case CODEC_ID_MPEG2VIDEO:
459 if (g_advancedSettings.m_stagefrightConfig.useMPEG2codec == 0)
461 mimetype = MEDIA_MIMETYPE_VIDEO_MPEG2;
467 if (g_advancedSettings.m_stagefrightConfig.useVPXcodec == 0)
469 mimetype = MEDIA_MIMETYPE_VIDEO_VPX;
473 if (g_advancedSettings.m_stagefrightConfig.useVC1codec == 0)
475 mimetype = MEDIA_MIMETYPE_VIDEO_WMV;
482 p->meta->setCString(kKeyMIMEType, mimetype);
483 p->meta->setInt32(kKeyWidth, p->width);
484 p->meta->setInt32(kKeyHeight, p->height);
486 android::ProcessState::self()->startThreadPool();
488 p->source = new CStageFrightMediaSource(p, p->meta);
489 p->client = new OMXClient;
491 if (p->source == NULL || p->client == NULL)
496 if (p->client->connect() != OK)
500 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot connect OMX client");
504 p->mVideoNativeWindow = NULL;
505 if ((p->quirks & QuirkSWRender) == 0)
507 p->InitStagefrightSurface();
508 native_window_api_connect(p->mVideoNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
511 p->decoder = OMXCodec::Create(p->client->interface(), p->meta,
512 false, p->source, NULL,
513 OMXCodec::kHardwareCodecsOnly | (p->quirks & QuirkSWRender ? OMXCodec::kClientNeedsFramebuffer : 0),
514 p->mVideoNativeWindow
517 if (!(p->decoder != NULL && p->decoder->start() == OK))
523 outFormat = p->decoder->getFormat();
525 if (!outFormat->findInt32(kKeyWidth, &p->width) || !outFormat->findInt32(kKeyHeight, &p->height)
526 || !outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat))
529 const char *component;
530 if (outFormat->findCString(kKeyDecoderComponent, &component))
532 CLog::Log(LOGDEBUG, "%s::%s - component: %s\n", CLASSNAME, __func__, component);
535 if (!strncmp(component, "OMX.Nvidia.mp4.decode", 21) && g_advancedSettings.m_stagefrightConfig.useMP4codec != 1)
537 // Has issues with some XVID encoded MP4. Only fails after actual decoding starts...
538 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (MP4)");
542 else if (!strncmp(component, "OMX.rk.", 7))
544 if (g_advancedSettings.m_stagefrightConfig.useAVCcodec != 1 && g_advancedSettings.m_stagefrightConfig.useMP4codec != 1)
546 if (p->width % 32 != 0 || p->height % 16 != 0)
548 // Buggy. Hard crash on non MOD16 height videos and stride errors for non MOD32 width
549 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (MOD16)");
557 cropLeft = cropTop = cropRight = cropBottom = 0;
558 if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
567 p->width = cropRight - cropLeft + 1;
568 p->height = cropBottom - cropTop + 1;
571 if (!outFormat->findInt32(kKeyStride, &p->videoStride))
572 p->videoStride = p->width;
573 if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
574 p->videoSliceHeight = p->height;
576 for (int i=0; i<INBUFCOUNT; ++i)
578 p->inbuf[i] = new MediaBuffer(300000);
579 p->inbuf[i]->setObserver(p);
582 p->decode_thread = new CStageFrightDecodeThread(p);
583 p->decode_thread->Create(true /*autodelete*/);
585 #if defined(DEBUG_VERBOSE)
586 CLog::Log(LOGDEBUG, ">>> format col:%d, w:%d, h:%d, sw:%d, sh:%d, ctl:%d,%d; cbr:%d,%d\n", p->videoColorFormat, p->width, p->height, p->videoStride, p->videoSliceHeight, cropTop, cropLeft, cropBottom, cropRight);
596 p->client->disconnect();
599 if (p->decoder_component)
600 free(&p->decoder_component);
601 if ((p->quirks & QuirkSWRender) == 0)
602 p->UninitStagefrightSurface();
607 int CStageFrightVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
609 #if defined(DEBUG_VERBOSE)
610 unsigned int time = XbmcThreads::SystemClockMillis();
611 CLog::Log(LOGDEBUG, "%s::Decode - d:%p; s:%d; dts:%f; pts:%f\n", CLASSNAME, pData, iSize, dts, pts);
615 int demuxer_bytes = iSize;
616 uint8_t *demuxer_content = pData;
620 frame = (Frame*)malloc(sizeof(Frame));
625 if (g_advancedSettings.m_stagefrightConfig.useInputDTS)
626 frame->pts = (dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : ((pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : 0);
628 frame->pts = (pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : ((dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : 0);
629 frame->medbuf = p->getBuffer(demuxer_bytes);
635 fast_memcpy(frame->medbuf->data(), demuxer_content, demuxer_bytes);
636 frame->medbuf->meta_data()->clear();
637 frame->medbuf->meta_data()->setInt64(kKeyTime, frame->pts);
641 p->in_queue.insert(std::pair<int64_t, Frame*>(p->framecount, frame));
642 p->in_condition.notify();
643 p->in_mutex.unlock();
647 if (p->inputBufferAvailable() && p->in_queue.size() < INBUFCOUNT)
651 if (p->cur_frame != NULL)
653 #if defined(DEBUG_VERBOSE)
654 CLog::Log(LOGDEBUG, "%s::Decode: pushed IN frame (%d); tm:%d\n", CLASSNAME,p->in_queue.size(), XbmcThreads::SystemClockMillis() - time);
660 bool CStageFrightVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
662 #if defined(DEBUG_VERBOSE)
663 unsigned int time = XbmcThreads::SystemClockMillis();
665 if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG && pDvdVideoPicture->eglimg != EGL_NO_IMAGE_KHR)
666 ReleaseBuffer(pDvdVideoPicture->eglimg);
669 if (p->prev_frame->medbuf)
670 p->prev_frame->medbuf->release();
672 p->prev_frame = NULL;
674 #if defined(DEBUG_VERBOSE)
675 CLog::Log(LOGDEBUG, "%s::ClearPicture (%d)\n", CLASSNAME, XbmcThreads::SystemClockMillis() - time);
681 bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
683 #if defined(DEBUG_VERBOSE)
684 unsigned int time = XbmcThreads::SystemClockMillis();
685 CLog::Log(LOGDEBUG, "%s::GetPicture\n", CLASSNAME);
686 if (p->cycle_time != 0)
687 CLog::Log(LOGDEBUG, ">>> cycle dur:%d\n", XbmcThreads::SystemClockMillis() - p->cycle_time);
688 p->cycle_time = time;
696 CLog::Log(LOGERROR, "%s::%s - Error getting frame\n", CLASSNAME, __func__);
697 p->out_condition.notify();
698 p->out_mutex.unlock();
702 Frame *frame = p->cur_frame;
703 status = frame->status;
705 pDvdVideoPicture->format = frame->format;
706 pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
707 pDvdVideoPicture->pts = frame->pts;
708 pDvdVideoPicture->iWidth = frame->width;
709 pDvdVideoPicture->iHeight = frame->height;
710 pDvdVideoPicture->iDisplayWidth = frame->width;
711 pDvdVideoPicture->iDisplayHeight = frame->height;
712 pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
713 pDvdVideoPicture->stf = this;
714 pDvdVideoPicture->eglimg = EGL_NO_IMAGE_KHR;
718 CLog::Log(LOGERROR, "%s::%s - Error getting picture from frame(%d)\n", CLASSNAME, __func__,status);
720 frame->medbuf->release();
724 p->out_condition.notify();
725 p->out_mutex.unlock();
729 if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG)
731 pDvdVideoPicture->eglimg = frame->eglimg;
732 #if defined(DEBUG_VERBOSE)
733 CLog::Log(LOGDEBUG, ">>> pic dts:%f, pts:%llu, img:%p, tm:%d\n", pDvdVideoPicture->dts, frame->pts, pDvdVideoPicture->eglimg, XbmcThreads::SystemClockMillis() - time);
736 else if (pDvdVideoPicture->format == RENDER_FMT_YUV420P)
738 pDvdVideoPicture->color_range = 0;
739 pDvdVideoPicture->color_matrix = 4;
741 unsigned int luma_pixels = frame->width * frame->height;
742 unsigned int chroma_pixels = luma_pixels/4;
743 uint8_t* data = NULL;
744 if (frame->medbuf && !p->drop_state)
746 data = (uint8_t*)((long)frame->medbuf->data() + frame->medbuf->range_offset());
748 switch (p->videoColorFormat)
750 case OMX_COLOR_FormatYUV420Planar:
751 pDvdVideoPicture->iLineSize[0] = frame->width;
752 pDvdVideoPicture->iLineSize[1] = frame->width / 2;
753 pDvdVideoPicture->iLineSize[2] = frame->width / 2;
754 pDvdVideoPicture->iLineSize[3] = 0;
755 pDvdVideoPicture->data[0] = data;
756 pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
757 pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
758 pDvdVideoPicture->data[3] = 0;
760 case OMX_COLOR_FormatYUV420SemiPlanar:
761 case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
762 case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
763 pDvdVideoPicture->iLineSize[0] = frame->width;
764 pDvdVideoPicture->iLineSize[1] = frame->width;
765 pDvdVideoPicture->iLineSize[2] = 0;
766 pDvdVideoPicture->iLineSize[3] = 0;
767 pDvdVideoPicture->data[0] = data;
768 pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
769 pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
770 pDvdVideoPicture->data[3] = 0;
773 CLog::Log(LOGERROR, "%s::%s - Unsupported color format(%d)\n", CLASSNAME, __func__,p->videoColorFormat);
775 #if defined(DEBUG_VERBOSE)
776 CLog::Log(LOGDEBUG, ">>> pic pts:%f, data:%p, col:%d, w:%d, h:%d, tm:%d\n", pDvdVideoPicture->pts, data, p->videoColorFormat, frame->width, frame->height, XbmcThreads::SystemClockMillis() - time);
781 pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
783 p->prev_frame = p->cur_frame;
785 p->out_condition.notify();
786 p->out_mutex.unlock();
791 void CStageFrightVideo::Close()
793 #if defined(DEBUG_VERBOSE)
794 CLog::Log(LOGDEBUG, "%s::Close\n", CLASSNAME);
799 if (p->decode_thread && p->decode_thread->IsRunning())
800 p->decode_thread->StopThread(false);
801 p->decode_thread = NULL;
802 p->in_condition.notify();
804 // Give decoder_thread time to process EOS, if stuck on reading
807 #if defined(DEBUG_VERBOSE)
808 CLog::Log(LOGDEBUG, "Cleaning OUT\n");
813 if (p->cur_frame->medbuf)
814 p->cur_frame->medbuf->release();
818 p->out_condition.notify();
819 p->out_mutex.unlock();
823 if (p->prev_frame->medbuf)
824 p->prev_frame->medbuf->release();
826 p->prev_frame = NULL;
829 #if defined(DEBUG_VERBOSE)
830 CLog::Log(LOGDEBUG, "Stopping omxcodec\n");
833 p->client->disconnect();
835 #if defined(DEBUG_VERBOSE)
836 CLog::Log(LOGDEBUG, "Cleaning IN(%d)\n", p->in_queue.size());
838 std::map<int64_t,Frame*>::iterator it;
839 while (!p->in_queue.empty())
841 it = p->in_queue.begin();
843 p->in_queue.erase(it);
845 frame->medbuf->release();
849 if (p->decoder_component)
850 free(&p->decoder_component);
854 if ((p->quirks & QuirkSWRender) == 0)
855 p->UninitStagefrightSurface();
857 for (int i=0; i<INBUFCOUNT; ++i)
859 p->inbuf[i]->setObserver(NULL);
860 p->inbuf[i]->release();
866 void CStageFrightVideo::Reset(void)
868 #if defined(DEBUG_VERBOSE)
869 CLog::Log(LOGDEBUG, "%s::Reset\n", CLASSNAME);
873 std::map<int64_t,Frame*>::iterator it;
874 while (!p->in_queue.empty())
876 it = p->in_queue.begin();
878 p->in_queue.erase(it);
880 frame->medbuf->release();
886 p->in_mutex.unlock();
889 void CStageFrightVideo::SetDropState(bool bDrop)
891 if (bDrop == p->drop_state)
894 #if defined(DEBUG_VERBOSE)
895 CLog::Log(LOGDEBUG, "%s::SetDropState (%d->%d)\n", CLASSNAME,p->drop_state,bDrop);
898 p->drop_state = bDrop;
901 void CStageFrightVideo::SetSpeed(int iSpeed)
907 void CStageFrightVideo::LockBuffer(EGLImageKHR eglimg)
909 #if defined(DEBUG_VERBOSE)
910 unsigned int time = XbmcThreads::SystemClockMillis();
912 p->free_mutex.lock();
913 std::list<std::pair<EGLImageKHR, int> >::iterator it = p->free_queue.begin();
914 for(;it != p->free_queue.end(); ++it)
916 if ((*it).first == eglimg)
919 if (it == p->free_queue.end())
921 p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
922 p->free_mutex.unlock();
925 #if defined(DEBUG_VERBOSE)
926 CLog::Log(LOGDEBUG, "Locking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
929 p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
930 p->free_queue.erase(it);
931 p->free_mutex.unlock();
934 void CStageFrightVideo::ReleaseBuffer(EGLImageKHR eglimg)
936 #if defined(DEBUG_VERBOSE)
937 unsigned int time = XbmcThreads::SystemClockMillis();
939 p->free_mutex.lock();
941 std::list<std::pair<EGLImageKHR, int> >::iterator it = p->busy_queue.begin();
942 std::list<std::pair<EGLImageKHR, int> >::iterator itfree;
943 for(;it != p->busy_queue.end(); ++it)
945 if ((*it).first == eglimg)
954 if (it == p->busy_queue.end() && !cnt)
956 p->free_mutex.unlock();
959 #if defined(DEBUG_VERBOSE)
960 CLog::Log(LOGDEBUG, "Unlocking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
965 p->free_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
966 p->busy_queue.erase(itfree);
968 p->free_mutex.unlock();