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)");
546 cropLeft = cropTop = cropRight = cropBottom = 0;
547 if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
556 p->width = cropRight - cropLeft + 1;
557 p->height = cropBottom - cropTop + 1;
560 if (!outFormat->findInt32(kKeyStride, &p->videoStride))
561 p->videoStride = p->width;
562 if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
563 p->videoSliceHeight = p->height;
565 for (int i=0; i<INBUFCOUNT; ++i)
567 p->inbuf[i] = new MediaBuffer(300000);
568 p->inbuf[i]->setObserver(p);
571 p->decode_thread = new CStageFrightDecodeThread(p);
572 p->decode_thread->Create(true /*autodelete*/);
574 #if defined(DEBUG_VERBOSE)
575 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);
585 p->client->disconnect();
588 if (p->decoder_component)
589 free(&p->decoder_component);
590 if ((p->quirks & QuirkSWRender) == 0)
591 p->UninitStagefrightSurface();
596 int CStageFrightVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
598 #if defined(DEBUG_VERBOSE)
599 unsigned int time = XbmcThreads::SystemClockMillis();
600 CLog::Log(LOGDEBUG, "%s::Decode - d:%p; s:%d; dts:%f; pts:%f\n", CLASSNAME, pData, iSize, dts, pts);
604 int demuxer_bytes = iSize;
605 uint8_t *demuxer_content = pData;
610 frame = (Frame*)malloc(sizeof(Frame));
615 if (g_advancedSettings.m_stagefrightConfig.useInputDTS)
616 frame->pts = (dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : ((pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : 0);
618 frame->pts = (pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : ((dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : 0);
620 // No valid pts? libstagefright asserts on this.
627 frame->medbuf = p->getBuffer(demuxer_bytes);
634 fast_memcpy(frame->medbuf->data(), demuxer_content, demuxer_bytes);
635 frame->medbuf->meta_data()->clear();
636 frame->medbuf->meta_data()->setInt64(kKeyTime, frame->pts);
640 p->in_queue.insert(std::pair<int64_t, Frame*>(p->framecount, frame));
641 p->in_condition.notify();
642 p->in_mutex.unlock();
645 if (p->inputBufferAvailable() && p->in_queue.size() < INBUFCOUNT)
649 if (p->cur_frame != NULL)
651 #if defined(DEBUG_VERBOSE)
652 CLog::Log(LOGDEBUG, "%s::Decode: pushed IN frame (%d); tm:%d\n", CLASSNAME,p->in_queue.size(), XbmcThreads::SystemClockMillis() - time);
658 bool CStageFrightVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
660 #if defined(DEBUG_VERBOSE)
661 unsigned int time = XbmcThreads::SystemClockMillis();
663 if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG && pDvdVideoPicture->eglimg != EGL_NO_IMAGE_KHR)
664 ReleaseBuffer(pDvdVideoPicture->eglimg);
667 if (p->prev_frame->medbuf)
668 p->prev_frame->medbuf->release();
670 p->prev_frame = NULL;
672 #if defined(DEBUG_VERBOSE)
673 CLog::Log(LOGDEBUG, "%s::ClearPicture (%d)\n", CLASSNAME, XbmcThreads::SystemClockMillis() - time);
679 bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
681 #if defined(DEBUG_VERBOSE)
682 unsigned int time = XbmcThreads::SystemClockMillis();
683 CLog::Log(LOGDEBUG, "%s::GetPicture\n", CLASSNAME);
684 if (p->cycle_time != 0)
685 CLog::Log(LOGDEBUG, ">>> cycle dur:%d\n", XbmcThreads::SystemClockMillis() - p->cycle_time);
686 p->cycle_time = time;
694 CLog::Log(LOGERROR, "%s::%s - Error getting frame\n", CLASSNAME, __func__);
695 p->out_condition.notify();
696 p->out_mutex.unlock();
700 Frame *frame = p->cur_frame;
701 status = frame->status;
703 pDvdVideoPicture->format = frame->format;
704 pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
705 pDvdVideoPicture->pts = frame->pts;
706 pDvdVideoPicture->iWidth = frame->width;
707 pDvdVideoPicture->iHeight = frame->height;
708 pDvdVideoPicture->iDisplayWidth = frame->width;
709 pDvdVideoPicture->iDisplayHeight = frame->height;
710 pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
711 pDvdVideoPicture->stf = this;
712 pDvdVideoPicture->eglimg = EGL_NO_IMAGE_KHR;
716 CLog::Log(LOGERROR, "%s::%s - Error getting picture from frame(%d)\n", CLASSNAME, __func__,status);
718 frame->medbuf->release();
722 p->out_condition.notify();
723 p->out_mutex.unlock();
727 if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG)
729 pDvdVideoPicture->eglimg = frame->eglimg;
730 #if defined(DEBUG_VERBOSE)
731 CLog::Log(LOGDEBUG, ">>> pic dts:%f, pts:%llu, img:%p, tm:%d\n", pDvdVideoPicture->dts, frame->pts, pDvdVideoPicture->eglimg, XbmcThreads::SystemClockMillis() - time);
734 else if (pDvdVideoPicture->format == RENDER_FMT_YUV420P)
736 pDvdVideoPicture->color_range = 0;
737 pDvdVideoPicture->color_matrix = 4;
739 unsigned int luma_pixels = frame->width * frame->height;
740 unsigned int chroma_pixels = luma_pixels/4;
741 uint8_t* data = NULL;
742 if (frame->medbuf && !p->drop_state)
744 data = (uint8_t*)((long)frame->medbuf->data() + frame->medbuf->range_offset());
746 switch (p->videoColorFormat)
748 case OMX_COLOR_FormatYUV420Planar:
749 pDvdVideoPicture->iLineSize[0] = frame->width;
750 pDvdVideoPicture->iLineSize[1] = frame->width / 2;
751 pDvdVideoPicture->iLineSize[2] = frame->width / 2;
752 pDvdVideoPicture->iLineSize[3] = 0;
753 pDvdVideoPicture->data[0] = data;
754 pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
755 pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
756 pDvdVideoPicture->data[3] = 0;
758 case OMX_COLOR_FormatYUV420SemiPlanar:
759 case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
760 case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
761 pDvdVideoPicture->iLineSize[0] = frame->width;
762 pDvdVideoPicture->iLineSize[1] = frame->width;
763 pDvdVideoPicture->iLineSize[2] = 0;
764 pDvdVideoPicture->iLineSize[3] = 0;
765 pDvdVideoPicture->data[0] = data;
766 pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
767 pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
768 pDvdVideoPicture->data[3] = 0;
771 CLog::Log(LOGERROR, "%s::%s - Unsupported color format(%d)\n", CLASSNAME, __func__,p->videoColorFormat);
773 #if defined(DEBUG_VERBOSE)
774 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);
779 pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
781 p->prev_frame = p->cur_frame;
783 p->out_condition.notify();
784 p->out_mutex.unlock();
789 void CStageFrightVideo::Close()
791 #if defined(DEBUG_VERBOSE)
792 CLog::Log(LOGDEBUG, "%s::Close\n", CLASSNAME);
797 if (p->decode_thread && p->decode_thread->IsRunning())
798 p->decode_thread->StopThread(false);
799 p->decode_thread = NULL;
800 p->in_condition.notify();
802 // Give decoder_thread time to process EOS, if stuck on reading
805 #if defined(DEBUG_VERBOSE)
806 CLog::Log(LOGDEBUG, "Cleaning OUT\n");
811 if (p->cur_frame->medbuf)
812 p->cur_frame->medbuf->release();
816 p->out_condition.notify();
817 p->out_mutex.unlock();
821 if (p->prev_frame->medbuf)
822 p->prev_frame->medbuf->release();
824 p->prev_frame = NULL;
827 #if defined(DEBUG_VERBOSE)
828 CLog::Log(LOGDEBUG, "Stopping omxcodec\n");
831 p->client->disconnect();
833 #if defined(DEBUG_VERBOSE)
834 CLog::Log(LOGDEBUG, "Cleaning IN(%d)\n", p->in_queue.size());
836 std::map<int64_t,Frame*>::iterator it;
837 while (!p->in_queue.empty())
839 it = p->in_queue.begin();
841 p->in_queue.erase(it);
843 frame->medbuf->release();
847 if (p->decoder_component)
848 free(&p->decoder_component);
852 if ((p->quirks & QuirkSWRender) == 0)
853 p->UninitStagefrightSurface();
855 for (int i=0; i<INBUFCOUNT; ++i)
857 p->inbuf[i]->setObserver(NULL);
858 p->inbuf[i]->release();
864 void CStageFrightVideo::Reset(void)
866 #if defined(DEBUG_VERBOSE)
867 CLog::Log(LOGDEBUG, "%s::Reset\n", CLASSNAME);
871 std::map<int64_t,Frame*>::iterator it;
872 while (!p->in_queue.empty())
874 it = p->in_queue.begin();
876 p->in_queue.erase(it);
878 frame->medbuf->release();
884 p->in_mutex.unlock();
887 void CStageFrightVideo::SetDropState(bool bDrop)
889 if (bDrop == p->drop_state)
892 #if defined(DEBUG_VERBOSE)
893 CLog::Log(LOGDEBUG, "%s::SetDropState (%d->%d)\n", CLASSNAME,p->drop_state,bDrop);
896 p->drop_state = bDrop;
899 void CStageFrightVideo::SetSpeed(int iSpeed)
905 void CStageFrightVideo::LockBuffer(EGLImageKHR eglimg)
907 #if defined(DEBUG_VERBOSE)
908 unsigned int time = XbmcThreads::SystemClockMillis();
910 p->free_mutex.lock();
911 std::list<std::pair<EGLImageKHR, int> >::iterator it = p->free_queue.begin();
912 for(;it != p->free_queue.end(); ++it)
914 if ((*it).first == eglimg)
917 if (it == p->free_queue.end())
919 p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
920 p->free_mutex.unlock();
923 #if defined(DEBUG_VERBOSE)
924 CLog::Log(LOGDEBUG, "Locking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
927 p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
928 p->free_queue.erase(it);
929 p->free_mutex.unlock();
932 void CStageFrightVideo::ReleaseBuffer(EGLImageKHR eglimg)
934 #if defined(DEBUG_VERBOSE)
935 unsigned int time = XbmcThreads::SystemClockMillis();
937 p->free_mutex.lock();
939 std::list<std::pair<EGLImageKHR, int> >::iterator it = p->busy_queue.begin();
940 std::list<std::pair<EGLImageKHR, int> >::iterator itfree;
941 for(;it != p->busy_queue.end(); ++it)
943 if ((*it).first == eglimg)
952 if (it == p->busy_queue.end() && !cnt)
954 p->free_mutex.unlock();
957 #if defined(DEBUG_VERBOSE)
958 CLog::Log(LOGDEBUG, "Unlocking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
963 p->free_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
964 p->busy_queue.erase(itfree);
966 p->free_mutex.unlock();