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"
43 #include "windowing/WindowingFactory.h"
47 #define OMX_QCOM_COLOR_FormatYVU420SemiPlanar 0x7FA30C00
48 #define OMX_TI_COLOR_FormatYUV420PackedSemiPlanar 0x7F000100
50 #define CLASSNAME "CStageFrightVideo"
52 #define EGL_NATIVE_BUFFER_ANDROID 0x3140
53 #define EGL_IMAGE_PRESERVED_KHR 0x30D2
55 const char *MEDIA_MIMETYPE_VIDEO_WMV = "video/x-ms-wmv";
57 using namespace android;
59 static int64_t pts_dtoi(double pts)
61 return (int64_t)(pts);
64 static double pts_itod(int64_t pts)
69 /***********************************************************/
71 class CStageFrightMediaSource : public MediaSource
74 CStageFrightMediaSource(CStageFrightVideoPrivate *priv, sp<MetaData> meta)
80 virtual sp<MetaData> getFormat()
85 virtual status_t start(MetaData *params)
90 virtual status_t stop()
95 virtual status_t read(MediaBuffer **buffer,
96 const MediaSource::ReadOptions *options)
101 int64_t time_us = -1;
102 MediaSource::ReadOptions::SeekMode mode;
104 if (options && options->getSeekTo(&time_us, &mode))
106 #if defined(DEBUG_VERBOSE)
107 CLog::Log(LOGDEBUG, "%s: reading source(%d): seek:%llu\n", CLASSNAME,p->in_queue.size(), time_us);
112 #if defined(DEBUG_VERBOSE)
113 CLog::Log(LOGDEBUG, "%s: reading source(%d)\n", CLASSNAME,p->in_queue.size());
118 while (p->in_queue.empty() && p->decode_thread)
119 p->in_condition.wait(p->in_mutex);
121 if (p->in_queue.empty())
123 p->in_mutex.unlock();
127 std::map<int64_t,Frame*>::iterator it = p->in_queue.begin();
130 *buffer = frame->medbuf;
132 p->in_queue.erase(it);
133 p->in_mutex.unlock();
135 #if defined(DEBUG_VERBOSE)
136 CLog::Log(LOGDEBUG, ">>> exiting reading source(%d); pts:%llu\n", p->in_queue.size(),frame->pts);
145 sp<MetaData> source_meta;
146 CStageFrightVideoPrivate *p;
149 /********************************************/
151 class CStageFrightDecodeThread : public CThread
154 CStageFrightVideoPrivate *p;
157 CStageFrightDecodeThread(CStageFrightVideoPrivate *priv)
158 : CThread("CStageFrightDecodeThread")
164 #if defined(DEBUG_VERBOSE)
165 CLog::Log(LOGDEBUG, "%s: entering decode thread\n", CLASSNAME);
171 #if defined(DEBUG_VERBOSE)
172 CLog::Log(LOGDEBUG, "%s: exited decode thread\n", CLASSNAME);
179 int32_t w, h, dw, dh;
181 int32_t keyframe = 0;
182 int32_t unreadable = 0;
183 MediaSource::ReadOptions readopt;
186 //SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
189 #if defined(DEBUG_VERBOSE)
190 unsigned int time = XbmcThreads::SystemClockMillis();
191 CLog::Log(LOGDEBUG, "%s: >>> Handling frame\n", CLASSNAME);
194 frame = (Frame*)malloc(sizeof(Frame));
201 frame->eglimg = EGL_NO_IMAGE_KHR;
202 frame->medbuf = NULL;
205 readopt.setSeekTo(0);
206 p->resetting = false;
208 frame->status = p->decoder->read(&frame->medbuf, &readopt);
209 readopt.clearSeekTo();
211 if (frame->status == OK)
213 if (!frame->medbuf->graphicBuffer().get()) // hw buffers
215 if (frame->medbuf->range_length() == 0)
217 CLog::Log(LOGERROR, "%s - Invalid buffer\n", CLASSNAME);
218 frame->status = VC_ERROR;
220 frame->medbuf->release();
221 frame->medbuf = NULL;
224 frame->format = RENDER_FMT_YUV420P;
227 frame->format = RENDER_FMT_EGLIMG;
230 if (frame->status == OK)
232 frame->width = p->width;
233 frame->height = p->height;
236 sp<MetaData> outFormat = p->decoder->getFormat();
237 outFormat->findInt32(kKeyWidth , &w);
238 outFormat->findInt32(kKeyHeight, &h);
240 // The OMX.SEC decoder doesn't signal the modified width/height
241 if (p->decoder_component && (w & 15 || h & 15) && !strncmp(p->decoder_component, "OMX.SEC", 7))
243 if (((w + 15)&~15) * ((h + 15)&~15) * 3/2 == frame->medbuf->range_length())
251 frame->medbuf->meta_data()->findInt64(kKeyTime, &(frame->pts));
253 else if (frame->status == INFO_FORMAT_CHANGED)
255 int32_t cropLeft, cropTop, cropRight, cropBottom;
256 sp<MetaData> outFormat = p->decoder->getFormat();
258 outFormat->findInt32(kKeyWidth , &p->width);
259 outFormat->findInt32(kKeyHeight, &p->height);
261 cropLeft = cropTop = cropRight = cropBottom = 0;
262 if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
271 p->width = cropRight - cropLeft + 1;
272 p->height = cropBottom - cropTop + 1;
274 outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat);
275 if (!outFormat->findInt32(kKeyStride, &p->videoStride))
276 p->videoStride = p->width;
277 if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
278 p->videoSliceHeight = p->height;
280 #if defined(DEBUG_VERBOSE)
281 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);
285 frame->medbuf->release();
286 frame->medbuf = NULL;
292 CLog::Log(LOGERROR, "%s - decoding error (%d)\n", CLASSNAME,frame->status);
294 frame->medbuf->release();
295 frame->medbuf = NULL;
300 if (frame->format == RENDER_FMT_EGLIMG)
302 if (!p->eglInitialized)
304 p->InitializeEGL(frame->width, frame->height);
306 else if (p->texwidth != frame->width || p->texheight != frame->height)
308 p->UninitializeEGL();
309 p->InitializeEGL(frame->width, frame->height);
312 if (p->free_queue.empty())
314 CLog::Log(LOGERROR, "%s::%s - Error: No free output buffers\n", CLASSNAME, __func__);
316 frame->medbuf->release();
321 ANativeWindowBuffer* graphicBuffer = frame->medbuf->graphicBuffer()->getNativeBuffer();
322 native_window_set_buffers_timestamp(p->mVideoNativeWindow.get(), frame->pts * 1000);
323 int err = p->mVideoNativeWindow.get()->queueBuffer(p->mVideoNativeWindow.get(), graphicBuffer);
325 frame->medbuf->meta_data()->setInt32(kKeyRendered, 1);
326 frame->medbuf->release();
327 frame->medbuf = NULL;
328 p->UpdateStagefrightTexture();
332 p->free_mutex.lock();
333 while (!p->free_queue.size())
335 std::list<std::pair<EGLImageKHR, int> >::iterator itfree = p->free_queue.begin();
336 int cur_slot = itfree->second;
337 p->fbo.BindToTexture(GL_TEXTURE_2D, p->slots[cur_slot].texid);
338 p->fbo.BeginRender();
340 glDisable(GL_DEPTH_TEST);
341 //glClear(GL_COLOR_BUFFER_BIT);
343 const GLfloat triangleVertices[] = {
350 glVertexAttribPointer(p->mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);
351 glEnableVertexAttribArray(p->mPositionHandle);
353 glUseProgram(p->mPgm);
354 glUniform1i(p->mTexSamplerHandle, 0);
356 glBindTexture(GL_TEXTURE_EXTERNAL_OES, p->mVideoTextureId);
358 GLfloat texMatrix[16];
359 // const GLfloat texMatrix[] = {
365 p->GetStagefrightTransformMatrix(texMatrix);
366 glUniformMatrix4fv(p->mTexMatrixHandle, 1, GL_FALSE, texMatrix);
368 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
370 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
371 // glDeleteTextures(1, &texid);
372 // eglDestroyImageKHR(p->eglDisplay, img);
375 glBindTexture(GL_TEXTURE_2D, 0);
377 frame->eglimg = p->slots[cur_slot].eglimg;
378 p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
379 p->free_queue.erase(itfree);
380 p->free_mutex.unlock();
384 #if defined(DEBUG_VERBOSE)
385 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);
389 p->cur_frame = frame;
391 p->out_condition.wait(p->out_mutex);
392 p->out_mutex.unlock();
394 while (!decode_done && !m_bStop);
396 if (p->eglInitialized)
397 p->UninitializeEGL();
402 /***********************************************************/
404 CStageFrightVideo::CStageFrightVideo(CWinSystemEGL* windowing, CAdvancedSettings* advsettings)
406 #if defined(DEBUG_VERBOSE)
407 CLog::Log(LOGDEBUG, "%s::ctor: %d\n", CLASSNAME, sizeof(CStageFrightVideo));
409 p = new CStageFrightVideoPrivate;
410 p->m_g_Windowing = windowing;
411 p->m_g_advancedSettings = advsettings;
414 CStageFrightVideo::~CStageFrightVideo()
419 bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
421 #if defined(DEBUG_VERBOSE)
422 CLog::Log(LOGDEBUG, "%s::Open\n", CLASSNAME);
425 CSingleLock lock(g_graphicsContext);
427 // stagefright crashes with null size. Trap this...
428 if (!hints.width || !hints.height)
430 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"null size, cannot handle");
433 p->width = hints.width;
434 p->height = hints.height;
436 if (p->m_g_advancedSettings->m_stagefrightConfig.useSwRenderer)
437 p->quirks |= QuirkSWRender;
439 sp<MetaData> outFormat;
440 int32_t cropLeft, cropTop, cropRight, cropBottom;
441 //Vector<String8> matchingCodecs;
443 p->meta = new MetaData;
446 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"cannot allocate MetaData");
450 const char* mimetype;
454 if (p->m_g_advancedSettings->m_stagefrightConfig.useAVCcodec == 0)
456 mimetype = MEDIA_MIMETYPE_VIDEO_AVC;
457 if ( *(char*)hints.extradata == 1 )
458 p->meta->setData(kKeyAVCC, kTypeAVCC, hints.extradata, hints.extrasize);
461 if (p->m_g_advancedSettings->m_stagefrightConfig.useMP4codec == 0)
463 mimetype = MEDIA_MIMETYPE_VIDEO_MPEG4;
465 case CODEC_ID_MPEG2VIDEO:
466 if (p->m_g_advancedSettings->m_stagefrightConfig.useMPEG2codec == 0)
468 mimetype = MEDIA_MIMETYPE_VIDEO_MPEG2;
474 if (p->m_g_advancedSettings->m_stagefrightConfig.useVPXcodec == 0)
476 mimetype = MEDIA_MIMETYPE_VIDEO_VPX;
480 if (p->m_g_advancedSettings->m_stagefrightConfig.useVC1codec == 0)
482 mimetype = MEDIA_MIMETYPE_VIDEO_WMV;
489 p->meta->setCString(kKeyMIMEType, mimetype);
490 p->meta->setInt32(kKeyWidth, p->width);
491 p->meta->setInt32(kKeyHeight, p->height);
493 android::ProcessState::self()->startThreadPool();
495 p->source = new CStageFrightMediaSource(p, p->meta);
496 p->client = new OMXClient;
498 if (p->source == NULL || p->client == NULL)
500 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot obtain source / client");
504 if (p->client->connect() != OK)
508 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot connect OMX client");
512 if ((p->quirks & QuirkSWRender) == 0)
513 p->InitStagefrightSurface();
515 p->decoder = OMXCodec::Create(p->client->interface(), p->meta,
516 false, p->source, NULL,
517 OMXCodec::kHardwareCodecsOnly | (p->quirks & QuirkSWRender ? OMXCodec::kClientNeedsFramebuffer : 0),
518 p->mVideoNativeWindow
521 if (!(p->decoder != NULL && p->decoder->start() == OK))
527 outFormat = p->decoder->getFormat();
529 if (!outFormat->findInt32(kKeyWidth, &p->width) || !outFormat->findInt32(kKeyHeight, &p->height)
530 || !outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat))
533 const char *component;
534 if (outFormat->findCString(kKeyDecoderComponent, &component))
536 CLog::Log(LOGDEBUG, "%s::%s - component: %s\n", CLASSNAME, __func__, component);
539 if (!strncmp(component, "OMX.google", 10))
541 // On some platforms, software decoders are returned anyway
542 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (software)");
545 else if (!strncmp(component, "OMX.Nvidia.mp4.decode", 21) && p->m_g_advancedSettings->m_stagefrightConfig.useMP4codec != 1)
547 // Has issues with some XVID encoded MP4. Only fails after actual decoding starts...
548 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (MP4)");
553 cropLeft = cropTop = cropRight = cropBottom = 0;
554 if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
563 p->width = cropRight - cropLeft + 1;
564 p->height = cropBottom - cropTop + 1;
567 if (!outFormat->findInt32(kKeyStride, &p->videoStride))
568 p->videoStride = p->width;
569 if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
570 p->videoSliceHeight = p->height;
572 for (int i=0; i<INBUFCOUNT; ++i)
574 p->inbuf[i] = new MediaBuffer(300000);
575 p->inbuf[i]->setObserver(p);
578 p->decode_thread = new CStageFrightDecodeThread(p);
579 p->decode_thread->Create(true /*autodelete*/);
581 #if defined(DEBUG_VERBOSE)
582 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);
589 int CStageFrightVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
591 #if defined(DEBUG_VERBOSE)
592 unsigned int time = XbmcThreads::SystemClockMillis();
593 CLog::Log(LOGDEBUG, "%s::Decode - d:%p; s:%d; dts:%f; pts:%f\n", CLASSNAME, pData, iSize, dts, pts);
597 int demuxer_bytes = iSize;
598 uint8_t *demuxer_content = pData;
603 frame = (Frame*)malloc(sizeof(Frame));
608 if (p->m_g_advancedSettings->m_stagefrightConfig.useInputDTS)
609 frame->pts = (dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : ((pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : 0);
611 frame->pts = (pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : ((dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : 0);
613 // No valid pts? libstagefright asserts on this.
620 frame->medbuf = p->getBuffer(demuxer_bytes);
627 fast_memcpy(frame->medbuf->data(), demuxer_content, demuxer_bytes);
628 frame->medbuf->meta_data()->clear();
629 frame->medbuf->meta_data()->setInt64(kKeyTime, frame->pts);
633 p->in_queue.insert(std::pair<int64_t, Frame*>(p->framecount, frame));
634 p->in_condition.notify();
635 p->in_mutex.unlock();
638 if (p->inputBufferAvailable() && p->in_queue.size() < INBUFCOUNT)
642 if (p->cur_frame != NULL)
644 #if defined(DEBUG_VERBOSE)
645 CLog::Log(LOGDEBUG, "%s::Decode: pushed IN frame (%d); tm:%d\n", CLASSNAME,p->in_queue.size(), XbmcThreads::SystemClockMillis() - time);
651 bool CStageFrightVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
653 #if defined(DEBUG_VERBOSE)
654 unsigned int time = XbmcThreads::SystemClockMillis();
656 if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG && pDvdVideoPicture->eglimg != EGL_NO_IMAGE_KHR)
657 ReleaseBuffer(pDvdVideoPicture->eglimg);
660 if (p->prev_frame->medbuf)
661 p->prev_frame->medbuf->release();
663 p->prev_frame = NULL;
665 #if defined(DEBUG_VERBOSE)
666 CLog::Log(LOGDEBUG, "%s::ClearPicture (%d)\n", CLASSNAME, XbmcThreads::SystemClockMillis() - time);
672 bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
674 #if defined(DEBUG_VERBOSE)
675 unsigned int time = XbmcThreads::SystemClockMillis();
676 CLog::Log(LOGDEBUG, "%s::GetPicture\n", CLASSNAME);
677 if (p->cycle_time != 0)
678 CLog::Log(LOGDEBUG, ">>> cycle dur:%d\n", XbmcThreads::SystemClockMillis() - p->cycle_time);
679 p->cycle_time = time;
687 CLog::Log(LOGERROR, "%s::%s - Error getting frame\n", CLASSNAME, __func__);
688 p->out_condition.notify();
689 p->out_mutex.unlock();
693 Frame *frame = p->cur_frame;
694 status = frame->status;
696 pDvdVideoPicture->format = frame->format;
697 pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
698 pDvdVideoPicture->pts = frame->pts;
699 pDvdVideoPicture->iWidth = frame->width;
700 pDvdVideoPicture->iHeight = frame->height;
701 pDvdVideoPicture->iDisplayWidth = frame->width;
702 pDvdVideoPicture->iDisplayHeight = frame->height;
703 pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
704 pDvdVideoPicture->eglimg = EGL_NO_IMAGE_KHR;
708 CLog::Log(LOGERROR, "%s::%s - Error getting picture from frame(%d)\n", CLASSNAME, __func__,status);
710 frame->medbuf->release();
714 p->out_condition.notify();
715 p->out_mutex.unlock();
719 if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG)
721 pDvdVideoPicture->eglimg = frame->eglimg;
722 #if defined(DEBUG_VERBOSE)
723 CLog::Log(LOGDEBUG, ">>> pic dts:%f, pts:%llu, img:%p, tm:%d\n", pDvdVideoPicture->dts, frame->pts, pDvdVideoPicture->eglimg, XbmcThreads::SystemClockMillis() - time);
726 else if (pDvdVideoPicture->format == RENDER_FMT_YUV420P)
728 pDvdVideoPicture->color_range = 0;
729 pDvdVideoPicture->color_matrix = 4;
731 unsigned int luma_pixels = frame->width * frame->height;
732 unsigned int chroma_pixels = luma_pixels/4;
733 uint8_t* data = NULL;
734 if (frame->medbuf && !p->drop_state)
736 data = (uint8_t*)((long)frame->medbuf->data() + frame->medbuf->range_offset());
738 switch (p->videoColorFormat)
740 case OMX_COLOR_FormatYUV420Planar:
741 pDvdVideoPicture->iLineSize[0] = frame->width;
742 pDvdVideoPicture->iLineSize[1] = frame->width / 2;
743 pDvdVideoPicture->iLineSize[2] = frame->width / 2;
744 pDvdVideoPicture->iLineSize[3] = 0;
745 pDvdVideoPicture->data[0] = data;
746 pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
747 pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
748 pDvdVideoPicture->data[3] = 0;
750 case OMX_COLOR_FormatYUV420SemiPlanar:
751 case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
752 case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
753 pDvdVideoPicture->iLineSize[0] = frame->width;
754 pDvdVideoPicture->iLineSize[1] = frame->width;
755 pDvdVideoPicture->iLineSize[2] = 0;
756 pDvdVideoPicture->iLineSize[3] = 0;
757 pDvdVideoPicture->data[0] = data;
758 pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
759 pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
760 pDvdVideoPicture->data[3] = 0;
763 CLog::Log(LOGERROR, "%s::%s - Unsupported color format(%d)\n", CLASSNAME, __func__,p->videoColorFormat);
765 #if defined(DEBUG_VERBOSE)
766 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);
771 pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
773 p->prev_frame = p->cur_frame;
775 p->out_condition.notify();
776 p->out_mutex.unlock();
781 void CStageFrightVideo::Close()
783 #if defined(DEBUG_VERBOSE)
784 CLog::Log(LOGDEBUG, "%s::Close\n", CLASSNAME);
789 if (p->decode_thread && p->decode_thread->IsRunning())
790 p->decode_thread->StopThread(false);
791 p->decode_thread = NULL;
792 p->in_condition.notify();
794 // Give decoder_thread time to process EOS, if stuck on reading
797 #if defined(DEBUG_VERBOSE)
798 CLog::Log(LOGDEBUG, "Cleaning OUT\n");
803 if (p->cur_frame->medbuf)
804 p->cur_frame->medbuf->release();
808 p->out_condition.notify();
809 p->out_mutex.unlock();
813 if (p->prev_frame->medbuf)
814 p->prev_frame->medbuf->release();
816 p->prev_frame = NULL;
819 #if defined(DEBUG_VERBOSE)
820 CLog::Log(LOGDEBUG, "Stopping omxcodec\n");
822 if (p->decoder != NULL)
825 p->client->disconnect();
827 #if defined(DEBUG_VERBOSE)
828 CLog::Log(LOGDEBUG, "Cleaning IN(%d)\n", p->in_queue.size());
830 std::map<int64_t,Frame*>::iterator it;
831 while (!p->in_queue.empty())
833 it = p->in_queue.begin();
835 p->in_queue.erase(it);
837 frame->medbuf->release();
841 #if defined(DEBUG_VERBOSE)
842 CLog::Log(LOGDEBUG, "Cleaning libstagefright\n", p->in_queue.size());
844 if ((p->quirks & QuirkSWRender) == 0)
845 p->UninitStagefrightSurface();
847 #if defined(DEBUG_VERBOSE)
848 CLog::Log(LOGDEBUG, "Final Cleaning\n", p->in_queue.size());
850 if (p->decoder_component)
851 free(&p->decoder_component);
855 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();