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);
302 frame->medbuf->release();
303 frame->medbuf = NULL;
308 if (frame->format == RENDER_FMT_EGLIMG)
310 if (!p->eglInitialized)
312 p->InitializeEGL(frame->width, frame->height);
314 else if (p->texwidth != frame->width || p->texheight != frame->height)
316 p->UninitializeEGL();
317 p->InitializeEGL(frame->width, frame->height);
320 if (p->free_queue.empty())
322 CLog::Log(LOGERROR, "%s::%s - Error: No free output buffers\n", CLASSNAME, __func__);
324 frame->medbuf->release();
329 ANativeWindowBuffer* graphicBuffer = frame->medbuf->graphicBuffer()->getNativeBuffer();
330 native_window_set_buffers_timestamp(p->mVideoNativeWindow.get(), frame->pts * 1000);
331 int err = p->mVideoNativeWindow.get()->queueBuffer(p->mVideoNativeWindow.get(), graphicBuffer);
333 frame->medbuf->meta_data()->setInt32(kKeyRendered, 1);
334 frame->medbuf->release();
335 frame->medbuf = NULL;
336 p->UpdateStagefrightTexture();
340 p->free_mutex.lock();
341 while (!p->free_queue.size())
343 std::list<std::pair<EGLImageKHR, int> >::iterator itfree = p->free_queue.begin();
344 int cur_slot = itfree->second;
345 p->fbo.BindToTexture(GL_TEXTURE_2D, p->slots[cur_slot].texid);
346 p->fbo.BeginRender();
348 glDisable(GL_DEPTH_TEST);
349 //glClear(GL_COLOR_BUFFER_BIT);
351 const GLfloat triangleVertices[] = {
358 glVertexAttribPointer(p->mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);
359 glEnableVertexAttribArray(p->mPositionHandle);
361 glUseProgram(p->mPgm);
362 glUniform1i(p->mTexSamplerHandle, 0);
364 glBindTexture(GL_TEXTURE_EXTERNAL_OES, p->mVideoTextureId);
366 GLfloat texMatrix[16];
367 // const GLfloat texMatrix[] = {
373 p->GetStagefrightTransformMatrix(texMatrix);
374 glUniformMatrix4fv(p->mTexMatrixHandle, 1, GL_FALSE, texMatrix);
376 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
378 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
379 // glDeleteTextures(1, &texid);
380 // eglDestroyImageKHR(p->eglDisplay, img);
383 glBindTexture(GL_TEXTURE_2D, 0);
385 frame->eglimg = p->slots[cur_slot].eglimg;
386 p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
387 p->free_queue.erase(itfree);
388 p->free_mutex.unlock();
392 #if defined(DEBUG_VERBOSE)
393 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);
397 p->cur_frame = frame;
399 p->out_condition.wait(p->out_mutex);
400 p->out_mutex.unlock();
402 while (!decode_done && !m_bStop);
404 if (p->eglInitialized)
405 p->UninitializeEGL();
410 /***********************************************************/
412 bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
414 #if defined(DEBUG_VERBOSE)
415 CLog::Log(LOGDEBUG, "%s::Open\n", CLASSNAME);
418 CSingleLock lock(g_graphicsContext);
420 // stagefright crashes with null size. Trap this...
421 if (!hints.width || !hints.height)
423 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"null size, cannot handle");
427 p = new CStageFrightVideoPrivate;
428 p->width = hints.width;
429 p->height = hints.height;
431 if (g_advancedSettings.m_stagefrightConfig.useSwRenderer)
432 p->quirks |= QuirkSWRender;
434 sp<MetaData> outFormat;
435 int32_t cropLeft, cropTop, cropRight, cropBottom;
436 //Vector<String8> matchingCodecs;
438 p->meta = new MetaData;
444 const char* mimetype;
448 if (g_advancedSettings.m_stagefrightConfig.useAVCcodec == 0)
450 mimetype = MEDIA_MIMETYPE_VIDEO_AVC;
451 if ( *(char*)hints.extradata == 1 )
452 p->meta->setData(kKeyAVCC, kTypeAVCC, hints.extradata, hints.extrasize);
455 if (g_advancedSettings.m_stagefrightConfig.useMP4codec == 0)
457 mimetype = MEDIA_MIMETYPE_VIDEO_MPEG4;
459 case CODEC_ID_MPEG2VIDEO:
460 if (g_advancedSettings.m_stagefrightConfig.useMPEG2codec == 0)
462 mimetype = MEDIA_MIMETYPE_VIDEO_MPEG2;
468 if (g_advancedSettings.m_stagefrightConfig.useVPXcodec == 0)
470 mimetype = MEDIA_MIMETYPE_VIDEO_VPX;
474 if (g_advancedSettings.m_stagefrightConfig.useVC1codec == 0)
476 mimetype = MEDIA_MIMETYPE_VIDEO_WMV;
483 p->meta->setCString(kKeyMIMEType, mimetype);
484 p->meta->setInt32(kKeyWidth, p->width);
485 p->meta->setInt32(kKeyHeight, p->height);
487 android::ProcessState::self()->startThreadPool();
489 p->source = new CStageFrightMediaSource(p, p->meta);
490 p->client = new OMXClient;
492 if (p->source == NULL || p->client == NULL)
497 if (p->client->connect() != OK)
501 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot connect OMX client");
505 if ((p->quirks & QuirkSWRender) == 0)
506 p->InitStagefrightSurface();
508 p->decoder = OMXCodec::Create(p->client->interface(), p->meta,
509 false, p->source, NULL,
510 OMXCodec::kHardwareCodecsOnly | (p->quirks & QuirkSWRender ? OMXCodec::kClientNeedsFramebuffer : 0),
511 p->mVideoNativeWindow
514 if (!(p->decoder != NULL && p->decoder->start() == OK))
520 outFormat = p->decoder->getFormat();
522 if (!outFormat->findInt32(kKeyWidth, &p->width) || !outFormat->findInt32(kKeyHeight, &p->height)
523 || !outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat))
526 const char *component;
527 if (outFormat->findCString(kKeyDecoderComponent, &component))
529 CLog::Log(LOGDEBUG, "%s::%s - component: %s\n", CLASSNAME, __func__, component);
532 if (!strncmp(component, "OMX.google", 10))
534 // On some platforms, software decoders are returned anyway
535 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (software)");
538 else if (!strncmp(component, "OMX.Nvidia.mp4.decode", 21) && g_advancedSettings.m_stagefrightConfig.useMP4codec != 1)
540 // Has issues with some XVID encoded MP4. Only fails after actual decoding starts...
541 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (MP4)");
544 else if (!strncmp(component, "OMX.rk.", 7))
546 if (g_advancedSettings.m_stagefrightConfig.useAVCcodec != 1 && g_advancedSettings.m_stagefrightConfig.useMP4codec != 1)
548 if (p->width % 32 != 0 || p->height % 16 != 0)
550 // Buggy. Hard crash on non MOD16 height videos and stride errors for non MOD32 width
551 CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (MOD16)");
559 cropLeft = cropTop = cropRight = cropBottom = 0;
560 if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
569 p->width = cropRight - cropLeft + 1;
570 p->height = cropBottom - cropTop + 1;
573 if (!outFormat->findInt32(kKeyStride, &p->videoStride))
574 p->videoStride = p->width;
575 if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
576 p->videoSliceHeight = p->height;
578 for (int i=0; i<INBUFCOUNT; ++i)
580 p->inbuf[i] = new MediaBuffer(300000);
581 p->inbuf[i]->setObserver(p);
584 p->decode_thread = new CStageFrightDecodeThread(p);
585 p->decode_thread->Create(true /*autodelete*/);
587 #if defined(DEBUG_VERBOSE)
588 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);
598 p->client->disconnect();
601 if (p->decoder_component)
602 free(&p->decoder_component);
603 if ((p->quirks & QuirkSWRender) == 0)
604 p->UninitStagefrightSurface();
609 int CStageFrightVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
611 #if defined(DEBUG_VERBOSE)
612 unsigned int time = XbmcThreads::SystemClockMillis();
613 CLog::Log(LOGDEBUG, "%s::Decode - d:%p; s:%d; dts:%f; pts:%f\n", CLASSNAME, pData, iSize, dts, pts);
617 int demuxer_bytes = iSize;
618 uint8_t *demuxer_content = pData;
622 frame = (Frame*)malloc(sizeof(Frame));
627 if (g_advancedSettings.m_stagefrightConfig.useInputDTS)
628 frame->pts = (dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : ((pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : 0);
630 frame->pts = (pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : ((dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : 0);
631 frame->medbuf = p->getBuffer(demuxer_bytes);
637 fast_memcpy(frame->medbuf->data(), demuxer_content, demuxer_bytes);
638 frame->medbuf->meta_data()->clear();
639 frame->medbuf->meta_data()->setInt64(kKeyTime, frame->pts);
643 p->in_queue.insert(std::pair<int64_t, Frame*>(p->framecount, frame));
644 p->in_condition.notify();
645 p->in_mutex.unlock();
649 if (p->inputBufferAvailable() && p->in_queue.size() < INBUFCOUNT)
653 if (p->cur_frame != NULL)
655 #if defined(DEBUG_VERBOSE)
656 CLog::Log(LOGDEBUG, "%s::Decode: pushed IN frame (%d); tm:%d\n", CLASSNAME,p->in_queue.size(), XbmcThreads::SystemClockMillis() - time);
662 bool CStageFrightVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
664 #if defined(DEBUG_VERBOSE)
665 unsigned int time = XbmcThreads::SystemClockMillis();
667 if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG && pDvdVideoPicture->eglimg != EGL_NO_IMAGE_KHR)
668 ReleaseBuffer(pDvdVideoPicture->eglimg);
671 if (p->prev_frame->medbuf)
672 p->prev_frame->medbuf->release();
674 p->prev_frame = NULL;
676 #if defined(DEBUG_VERBOSE)
677 CLog::Log(LOGDEBUG, "%s::ClearPicture (%d)\n", CLASSNAME, XbmcThreads::SystemClockMillis() - time);
683 bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
685 #if defined(DEBUG_VERBOSE)
686 unsigned int time = XbmcThreads::SystemClockMillis();
687 CLog::Log(LOGDEBUG, "%s::GetPicture\n", CLASSNAME);
688 if (p->cycle_time != 0)
689 CLog::Log(LOGDEBUG, ">>> cycle dur:%d\n", XbmcThreads::SystemClockMillis() - p->cycle_time);
690 p->cycle_time = time;
698 CLog::Log(LOGERROR, "%s::%s - Error getting frame\n", CLASSNAME, __func__);
699 p->out_condition.notify();
700 p->out_mutex.unlock();
704 Frame *frame = p->cur_frame;
705 status = frame->status;
707 pDvdVideoPicture->format = frame->format;
708 pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
709 pDvdVideoPicture->pts = frame->pts;
710 pDvdVideoPicture->iWidth = frame->width;
711 pDvdVideoPicture->iHeight = frame->height;
712 pDvdVideoPicture->iDisplayWidth = frame->width;
713 pDvdVideoPicture->iDisplayHeight = frame->height;
714 pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
715 pDvdVideoPicture->stf = this;
716 pDvdVideoPicture->eglimg = EGL_NO_IMAGE_KHR;
720 CLog::Log(LOGERROR, "%s::%s - Error getting picture from frame(%d)\n", CLASSNAME, __func__,status);
722 frame->medbuf->release();
726 p->out_condition.notify();
727 p->out_mutex.unlock();
731 if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG)
733 pDvdVideoPicture->eglimg = frame->eglimg;
734 #if defined(DEBUG_VERBOSE)
735 CLog::Log(LOGDEBUG, ">>> pic dts:%f, pts:%llu, img:%p, tm:%d\n", pDvdVideoPicture->dts, frame->pts, pDvdVideoPicture->eglimg, XbmcThreads::SystemClockMillis() - time);
738 else if (pDvdVideoPicture->format == RENDER_FMT_YUV420P)
740 pDvdVideoPicture->color_range = 0;
741 pDvdVideoPicture->color_matrix = 4;
743 unsigned int luma_pixels = frame->width * frame->height;
744 unsigned int chroma_pixels = luma_pixels/4;
745 uint8_t* data = NULL;
746 if (frame->medbuf && !p->drop_state)
748 data = (uint8_t*)((long)frame->medbuf->data() + frame->medbuf->range_offset());
750 switch (p->videoColorFormat)
752 case OMX_COLOR_FormatYUV420Planar:
753 pDvdVideoPicture->iLineSize[0] = frame->width;
754 pDvdVideoPicture->iLineSize[1] = frame->width / 2;
755 pDvdVideoPicture->iLineSize[2] = frame->width / 2;
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;
762 case OMX_COLOR_FormatYUV420SemiPlanar:
763 case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
764 case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
765 pDvdVideoPicture->iLineSize[0] = frame->width;
766 pDvdVideoPicture->iLineSize[1] = frame->width;
767 pDvdVideoPicture->iLineSize[2] = 0;
768 pDvdVideoPicture->iLineSize[3] = 0;
769 pDvdVideoPicture->data[0] = data;
770 pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
771 pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
772 pDvdVideoPicture->data[3] = 0;
775 CLog::Log(LOGERROR, "%s::%s - Unsupported color format(%d)\n", CLASSNAME, __func__,p->videoColorFormat);
777 #if defined(DEBUG_VERBOSE)
778 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);
783 pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
785 p->prev_frame = p->cur_frame;
787 p->out_condition.notify();
788 p->out_mutex.unlock();
793 void CStageFrightVideo::Close()
795 #if defined(DEBUG_VERBOSE)
796 CLog::Log(LOGDEBUG, "%s::Close\n", CLASSNAME);
801 if (p->decode_thread && p->decode_thread->IsRunning())
802 p->decode_thread->StopThread(false);
803 p->decode_thread = NULL;
804 p->in_condition.notify();
806 // Give decoder_thread time to process EOS, if stuck on reading
809 #if defined(DEBUG_VERBOSE)
810 CLog::Log(LOGDEBUG, "Cleaning OUT\n");
815 if (p->cur_frame->medbuf)
816 p->cur_frame->medbuf->release();
820 p->out_condition.notify();
821 p->out_mutex.unlock();
825 if (p->prev_frame->medbuf)
826 p->prev_frame->medbuf->release();
828 p->prev_frame = NULL;
831 #if defined(DEBUG_VERBOSE)
832 CLog::Log(LOGDEBUG, "Stopping omxcodec\n");
835 p->client->disconnect();
837 #if defined(DEBUG_VERBOSE)
838 CLog::Log(LOGDEBUG, "Cleaning IN(%d)\n", p->in_queue.size());
840 std::map<int64_t,Frame*>::iterator it;
841 while (!p->in_queue.empty())
843 it = p->in_queue.begin();
845 p->in_queue.erase(it);
847 frame->medbuf->release();
851 if (p->decoder_component)
852 free(&p->decoder_component);
856 if ((p->quirks & QuirkSWRender) == 0)
857 p->UninitStagefrightSurface();
859 for (int i=0; i<INBUFCOUNT; ++i)
861 p->inbuf[i]->setObserver(NULL);
862 p->inbuf[i]->release();
868 void CStageFrightVideo::Reset(void)
870 #if defined(DEBUG_VERBOSE)
871 CLog::Log(LOGDEBUG, "%s::Reset\n", CLASSNAME);
875 std::map<int64_t,Frame*>::iterator it;
876 while (!p->in_queue.empty())
878 it = p->in_queue.begin();
880 p->in_queue.erase(it);
882 frame->medbuf->release();
888 p->in_mutex.unlock();
891 void CStageFrightVideo::SetDropState(bool bDrop)
893 if (bDrop == p->drop_state)
896 #if defined(DEBUG_VERBOSE)
897 CLog::Log(LOGDEBUG, "%s::SetDropState (%d->%d)\n", CLASSNAME,p->drop_state,bDrop);
900 p->drop_state = bDrop;
903 void CStageFrightVideo::SetSpeed(int iSpeed)
909 void CStageFrightVideo::LockBuffer(EGLImageKHR eglimg)
911 #if defined(DEBUG_VERBOSE)
912 unsigned int time = XbmcThreads::SystemClockMillis();
914 p->free_mutex.lock();
915 std::list<std::pair<EGLImageKHR, int> >::iterator it = p->free_queue.begin();
916 for(;it != p->free_queue.end(); ++it)
918 if ((*it).first == eglimg)
921 if (it == p->free_queue.end())
923 p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
924 p->free_mutex.unlock();
927 #if defined(DEBUG_VERBOSE)
928 CLog::Log(LOGDEBUG, "Locking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
931 p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
932 p->free_queue.erase(it);
933 p->free_mutex.unlock();
936 void CStageFrightVideo::ReleaseBuffer(EGLImageKHR eglimg)
938 #if defined(DEBUG_VERBOSE)
939 unsigned int time = XbmcThreads::SystemClockMillis();
941 p->free_mutex.lock();
943 std::list<std::pair<EGLImageKHR, int> >::iterator it = p->busy_queue.begin();
944 std::list<std::pair<EGLImageKHR, int> >::iterator itfree;
945 for(;it != p->busy_queue.end(); ++it)
947 if ((*it).first == eglimg)
956 if (it == p->busy_queue.end() && !cnt)
958 p->free_mutex.unlock();
961 #if defined(DEBUG_VERBOSE)
962 CLog::Log(LOGDEBUG, "Unlocking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
967 p->free_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
968 p->busy_queue.erase(itfree);
970 p->free_mutex.unlock();