2 Copyright 2004-2005 Chris Tallon, 2009 Marten Richter
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "mtdraspberry.h"
25 #include "osdopengl.h"
30 //A lot of parts of this file are heavily inspired by xbmc omx implementations
32 VideoOMX::VideoOMX() {
37 cur_input_buf_omx = NULL;
38 omx_h264 = omx_mpeg2 = true;
42 offsetvideonotset = true;
43 offsetaudionotset = true;
61 int VideoOMX::init(UCHAR tformat)
63 if (initted) return 0;
66 if (!setFormat(tformat)) { shutdown(); return 0; }
67 if (!setConnection(COMPOSITERGB)) { shutdown(); return 0; }
68 if (!setAspectRatio(ASPECT4X3)) { shutdown(); return 0; }
69 if (!setMode(NORMAL)) { shutdown(); return 0; }
70 if (!setSource()) { shutdown(); return 0; }
71 if (!attachFrameBuffer()) { shutdown(); return 0; }
86 int VideoOMX::initUsingOSDObjects()
89 // we are called before the audio
92 if (error!=OMX_ErrorNone) {
93 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX failed %x", error);
101 OMX_ERRORTYPE VideoOMX::EventHandler_OMX(OMX_IN OMX_HANDLETYPE handle,OMX_IN OMX_PTR appdata,
102 OMX_IN OMX_EVENTTYPE event_type,OMX_IN OMX_U32 data1,
103 OMX_IN OMX_U32 data2,OMX_IN OMX_PTR event_data) {
105 Log::getInstance()->log("Video", Log::NOTICE, "eventHandler %x %x %x %x %x",handle,event_type,data1,data2,event_data);
107 struct VPE_OMX_EVENT new_event;
108 new_event.handle=handle;
109 new_event.appdata=appdata;
110 new_event.event_type=event_type;
111 new_event.data1=data1;
112 new_event.data2=data2;
113 new_event.event_data=event_data;
115 VideoOMX *video=(VideoOMX *)getInstance();
116 video->AddOmxEvent(new_event);
118 /* switch (event_type) {
119 case OMX_EventCmdComplete: {
124 return OMX_ErrorNone;
128 void VideoOMX::AddOmxEvent(VPE_OMX_EVENT new_event)
130 omx_event_mutex.Lock();
131 omx_events.push_back(new_event);
132 omx_event_mutex.Unlock();
136 OMX_ERRORTYPE VideoOMX::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer){
138 //Log::getInstance()->log("Video", Log::NOTICE, "EmptyBufferDone");
139 VideoOMX *video=(VideoOMX *)getInstance();
140 video->ReturnEmptyOMXBuffer(buffer);
141 return OMX_ErrorNone;
145 void VideoOMX::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){
146 input_bufs_omx_mutex.Lock();
147 // Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d %d %d",input_bufs_omx_free.size(),input_bufs_omx_present.size(),input_bufs_omx_all.size());
148 input_bufs_omx_free.push_back(buffer);
149 //Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size());
150 input_bufs_omx_mutex.Unlock();
153 OMX_ERRORTYPE VideoOMX::FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer) {
154 Log::getInstance()->log("Video", Log::NOTICE, "FillBufferDone");
155 return OMX_ErrorNone;
160 int VideoOMX::shutdown()
162 if (!initted) return 0;
165 DeAllocateCodecsOMX();
171 int VideoOMX::setTVsize(UCHAR ttvsize)
175 // Override the aspect ratio usage, temporarily use to set the video chip mode
176 if (!setAspectRatio(tvsize)) { shutdown(); return 0; }
178 if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
179 if (!setSource()) { shutdown(); return 0; }
180 if (!attachFramebuffer()) { shutdown(); return 0; }
182 // Reopening the fd causes the scart aspect line to go back to 4:3
183 // Set this again to the same as the tv screen size
184 if (!setAspectRatio(tvsize)) { shutdown(); return 0; }
186 // mode == LETTERBOX is invalid if the TV is widescreen
187 if (tvsize == ASPECT16X9) setMode(NORMAL);
192 int VideoOMX::setDefaultAspect()
194 return setAspectRatio(tvsize);
199 int VideoOMX::setFormat(UCHAR tformat)
201 if (!initted) return 0;
202 if ((tformat != PAL) && (tformat != NTSC)) return 0;
205 // if (ioctl(fdVideo, AV_SET_VID_DISP_FMT, format) != 0) return 0;
221 int VideoOMX::setConnection(UCHAR tconnection)
223 if (!initted) return 0;
224 if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;
225 connection = tconnection;
227 // if (ioctl(fdVideo, AV_SET_VID_OUTPUT, connection) != 0) return 0;
231 int VideoOMX::setAspectRatio(UCHAR taspectRatio)
233 if (!initted) return 0;
234 if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
235 aspectRatio = taspectRatio;
237 Log::getInstance()->log("Video", Log::DEBUG, "Setting aspect to %i", aspectRatio);
239 // if (ioctl(fdVideo, AV_SET_VID_RATIO, aspectRatio) != 0) return 0;
243 int VideoOMX::setMode(UCHAR tmode)
245 if (!initted) return 0;
252 void VideoOMX::updateMode()
257 OMX_CONFIG_DISPLAYREGIONTYPE dispconf;
258 memset(&dispconf, 0, sizeof(dispconf));
259 dispconf.nSize = sizeof(dispconf);
260 dispconf.nVersion.nVersion = OMX_VERSION;
261 dispconf.nPortIndex = omx_rend_input_port;
263 dispconf.set = OMX_DISPLAY_SET_LAYER;
264 error = OMX_SetParameter(omx_vid_rend, OMX_IndexConfigDisplayRegion,
266 if (error != OMX_ErrorNone) {
267 Log::getInstance()->log("Video", Log::DEBUG,
268 "Set OMX_IndexConfigDisplayRegion1 failed %x", error);
269 clock_mutex.Unlock();
272 dispconf.set = OMX_DISPLAY_SET_FULLSCREEN;
273 if (mode != QUARTER && mode != EIGHTH) {
275 dispconf.fullscreen = OMX_TRUE;
277 dispconf.fullscreen = OMX_FALSE;
279 error = OMX_SetParameter(omx_vid_rend, OMX_IndexConfigDisplayRegion,
281 if (error != OMX_ErrorNone) {
282 Log::getInstance()->log("Video", Log::DEBUG,
283 "Set OMX_IndexConfigDisplayRegion2 failed %x", error);
284 clock_mutex.Unlock();
288 dispconf.set = OMX_DISPLAY_SET_MODE;
289 if (mode != QUARTER && mode != EIGHTH) {
290 dispconf.mode = (mode == NORMAL) ? OMX_DISPLAY_MODE_FILL
291 : OMX_DISPLAY_MODE_LETTERBOX;
293 dispconf.mode = OMX_DISPLAY_MODE_LETTERBOX;
295 error = OMX_SetParameter(omx_vid_rend, OMX_IndexConfigDisplayRegion,
297 if (error != OMX_ErrorNone) {
298 Log::getInstance()->log("Video", Log::DEBUG,
299 "Set OMX_IndexConfigDisplayRegion3 failed %x", error);
300 clock_mutex.Unlock();
304 if (mode == QUARTER || mode == EIGHTH) {
305 unsigned int display_width, display_height;
306 display_width = display_height = 0;
307 if (graphics_get_display_size(0, &display_width, &display_height)
309 Log::getInstance()->log("OSD", Log::WARN,
310 "Getting display size failed! (BCM API) ");
311 clock_mutex.Unlock();
314 //UnSetFullscreen with window
315 dispconf.set = OMX_DISPLAY_SET_DEST_RECT;
316 dispconf.dest_rect.x_offset
317 = (int) (xpos * ((float) display_width));
318 dispconf.dest_rect.y_offset = (int) (ypos
319 * ((float) display_height));
320 if (mode == QUARTER) {
321 dispconf.dest_rect.width = display_width >> 1;
322 dispconf.dest_rect.height = display_height >> 1;
323 } else if (mode == EIGHTH) {
324 dispconf.dest_rect.width = display_width >> 2;
325 dispconf.dest_rect.height = display_height >> 2;
327 error = OMX_SetParameter(omx_vid_rend,
328 OMX_IndexConfigDisplayRegion, &dispconf);
329 if (error != OMX_ErrorNone) {
330 Log::getInstance()->log("Video", Log::DEBUG,
331 "Set OMX_IndexConfigDisplayRegion failed %x", error);
332 clock_mutex.Unlock();
338 clock_mutex.Unlock();
341 int VideoOMX::signalOff()
343 // if (ioctl(fdVideo, AV_SET_VID_DENC, 0) != 0) return 0;
347 int VideoOMX::signalOn()
349 // if (ioctl(fdVideo, AV_SET_VID_DENC, 1) != 0) return 0;
353 int VideoOMX::setSource()
355 if (!initted) return 0;
357 // What does this do...
358 // if (ioctl(fdVideo, AV_SET_VID_SRC, 1) != 0) return 0;
362 int VideoOMX::setPosition(int x, int y) {
365 xpos = ((float) x*2.f) / ((float) screenWidth);
366 ypos = ((float) y*2.f) / ((float) screenHeight);
374 if (!initted) return 0;
376 // if (ioctl(fdVideo, AV_SET_VID_SYNC, 2) != 0) return 0;
381 int VideoOMX::play() {
385 Log::getInstance()->log("Video", Log::DEBUG, "enter play");
387 if (AllocateCodecsOMX()) {
389 // Otherwise fall back to libav
393 Log::getInstance()->log("Video", Log::NOTICE,
394 "Allocate Codecs OMX failed assume h264 unsupported");
397 Log::getInstance()->log("Video", Log::NOTICE,
398 "Allocate Codecs OMX failed assume mpeg2 unsupported");
407 int VideoOMX::initClock()
411 if (clock_references==0)
414 static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
417 error=OMX_GetHandle(&omx_clock,VPE_OMX_CLOCK,NULL,&callbacks);
419 if (error!=OMX_ErrorNone) {
420 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX clock failed %x", error);
421 clock_mutex.Unlock();
422 DeAllocateCodecsOMX();
426 /* TODO Clock config to separate method */
427 OMX_PORT_PARAM_TYPE p_param;
428 memset(&p_param,0,sizeof(p_param));
429 p_param.nSize=sizeof(p_param);
430 p_param.nVersion.nVersion=OMX_VERSION;
431 error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param);
432 if (error!=OMX_ErrorNone) {
433 Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error);
434 clock_mutex.Unlock();
435 DeAllocateCodecsOMX();
438 omx_clock_output_port=p_param.nStartPortNumber;
440 for (unsigned int i=0;i<p_param.nPorts;i++) {
441 if (!DisablePort(omx_clock,p_param.nStartPortNumber+i,true) ) {
442 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX clock failed %d",i);
443 clock_mutex.Unlock();
444 DeAllocateCodecsOMX();
453 Log::getInstance()->log("Video", Log::DEBUG, "init omx clock %x %x",this,omx_clock);
455 clock_mutex.Unlock();
459 int VideoOMX::getClockAudioandInit(OMX_HANDLETYPE *p_omx_clock,OMX_U32 *p_omx_clock_output_port)
463 *p_omx_clock_output_port=0;
470 OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refclock;
471 memset(&refclock,0,sizeof(refclock));
472 refclock.nSize=sizeof(refclock);
473 refclock.nVersion.nVersion=OMX_VERSION;
475 refclock.eClock=OMX_TIME_RefClockAudio;
477 //refclock.eClock=OMX_TIME_RefClockVideo;
478 error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeActiveRefClock,&refclock);
479 if (error!=OMX_ErrorNone){
480 Log::getInstance()->log("Video", Log::DEBUG, "Clock OMX_IndexConfigTimeActiveRefClock failed %x", error);
481 clock_mutex.Unlock();
482 DeAllocateCodecsOMX();
486 OMX_PORT_PARAM_TYPE p_param;
487 memset(&p_param,0,sizeof(p_param));
488 p_param.nSize=sizeof(p_param);
489 p_param.nVersion.nVersion=OMX_VERSION;
490 error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param);
491 if (error!=OMX_ErrorNone){
492 Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error);
493 clock_mutex.Unlock();
494 DeAllocateCodecsOMX();
498 OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
499 memset(&clock_conf,0,sizeof(clock_conf));
500 clock_conf.nSize=sizeof(clock_conf);
501 clock_conf.nVersion.nVersion=OMX_VERSION;
502 clock_conf.eState=OMX_TIME_ClockStateWaitingForStartTime;
503 clock_conf.nStartTime=0;
504 clock_conf.nOffset=0;
505 if (clock_references==1) clock_conf.nWaitMask=OMX_CLOCKPORT1;
506 else clock_conf.nWaitMask=OMX_CLOCKPORT0|OMX_CLOCKPORT1;
507 error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
508 if (error!=OMX_ErrorNone) {
509 Log::getInstance()->log("Video", Log::DEBUG, "AuI Clock IndexConfigTimeClockState failed %x", error);
513 *p_omx_clock_output_port=p_param.nStartPortNumber+1;
514 *p_omx_clock=omx_clock;
515 clock_mutex.Unlock();
519 int VideoOMX::getClockVideoandInit()
528 if (clock_references==1) { // only if no audio is attached to this clock!
529 OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refclock;
530 memset(&refclock,0,sizeof(refclock));
531 refclock.nSize=sizeof(refclock);
532 refclock.nVersion.nVersion=OMX_VERSION;
534 //refclock.eClock=OMX_TIME_RefClockAudio;
536 refclock.eClock=OMX_TIME_RefClockVideo;
537 error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeActiveRefClock,&refclock);
538 if (error!=OMX_ErrorNone) {
539 Log::getInstance()->log("Video", Log::DEBUG, "Clock OMX_IndexConfigTimeActiveRefClock failed %x", error);
540 clock_mutex.Unlock();
541 DeAllocateCodecsOMX();
546 OMX_PORT_PARAM_TYPE p_param;
547 memset(&p_param,0,sizeof(p_param));
548 p_param.nSize=sizeof(p_param);
549 p_param.nVersion.nVersion=OMX_VERSION;
550 error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param);
551 if (error!=OMX_ErrorNone){
552 Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error);
553 clock_mutex.Unlock();
554 DeAllocateCodecsOMX();
559 OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
560 memset(&clock_conf,0,sizeof(clock_conf));
561 clock_conf.nSize=sizeof(clock_conf);
562 clock_conf.nVersion.nVersion=OMX_VERSION;
563 clock_conf.eState=OMX_TIME_ClockStateWaitingForStartTime;
564 clock_conf.nStartTime=0;
565 clock_conf.nOffset=0;
566 if (clock_references==1) clock_conf.nWaitMask=OMX_CLOCKPORT0;
567 else clock_conf.nWaitMask=OMX_CLOCKPORT0|OMX_CLOCKPORT1;
568 error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
569 if (error!=OMX_ErrorNone) {
570 Log::getInstance()->log("Video", Log::DEBUG, "VuI Clock IndexConfigTimeClockState failed %x", error);
573 omx_clock_output_port=p_param.nStartPortNumber;
574 clock_mutex.Unlock();
579 void VideoOMX::clockUnpause()
583 OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
584 memset(&clock_conf,0,sizeof(clock_conf));
585 clock_conf.nSize=sizeof(clock_conf);
586 clock_conf.nVersion.nVersion=OMX_VERSION;
587 clock_conf.eState=OMX_TIME_ClockStateRunning;
588 clock_conf.nStartTime=0;
589 clock_conf.nOffset=0;
590 clock_conf.nWaitMask=OMX_CLOCKPORT1;
591 error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
592 if (error!=OMX_ErrorNone) {
593 Log::getInstance()->log("Video", Log::DEBUG, "ClockUnpause IndexConfigTimeClockState failed %x", error);
596 clock_mutex.Unlock();
600 void VideoOMX::clockPause()
604 OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
605 memset(&clock_conf,0,sizeof(clock_conf));
606 clock_conf.nSize=sizeof(clock_conf);
607 clock_conf.nVersion.nVersion=OMX_VERSION;
608 clock_conf.eState=OMX_TIME_ClockStateStopped;
609 clock_conf.nStartTime=0;
610 clock_conf.nOffset=0;
611 clock_conf.nWaitMask=OMX_CLOCKPORT1;
612 error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
613 if (error!=OMX_ErrorNone) {
614 Log::getInstance()->log("Video", Log::DEBUG, "ClockUnpause IndexConfigTimeClockState failed %x", error);
616 clock_mutex.Unlock();
621 int VideoOMX::AllocateCodecsOMX()
624 static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
626 Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX");
627 //Clock, move later to audio including events
629 Log::getInstance()->log("Video", Log::DEBUG, "Nmark1 ");
630 if (!getClockVideoandInit()){
631 return 0;// get the clock and init it if necessary
633 Log::getInstance()->log("Video", Log::DEBUG, "Nmark2 ");
636 Log::getInstance()->log("Video", Log::DEBUG, "idleClock failed");
644 error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_H264_DECODER,NULL,&callbacks);
646 error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_MPEG2_DECODER,NULL,&callbacks);
649 if (error!=OMX_ErrorNone){
650 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video decoder failed %x", error);
651 clock_mutex.Unlock();
652 DeAllocateCodecsOMX();
657 Log::getInstance()->log("Video", Log::DEBUG, "Nmark3 ");
658 OMX_PORT_PARAM_TYPE p_param;
659 memset(&p_param,0,sizeof(p_param));
660 p_param.nSize=sizeof(p_param);
661 p_param.nVersion.nVersion=OMX_VERSION;
662 error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamVideoInit,&p_param);
663 if (error!=OMX_ErrorNone){
664 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX h264 decoder OMX_GetParameter failed %x", error);
665 clock_mutex.Unlock();
666 DeAllocateCodecsOMX();
669 omx_codec_input_port=p_param.nStartPortNumber;
670 omx_codec_output_port=p_param.nStartPortNumber+1;
672 if (!DisablePort(omx_vid_dec,omx_codec_input_port) || !DisablePort(omx_vid_dec,omx_codec_output_port)) {
673 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video decoder failed");
674 clock_mutex.Unlock();
675 DeAllocateCodecsOMX();
679 Log::getInstance()->log("Video", Log::DEBUG, "Nmark4 ");
681 OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE conceal;
682 memset(&conceal,0,sizeof(conceal));
683 conceal.nSize=sizeof(conceal);
684 conceal.nVersion.nVersion=OMX_VERSION;
685 conceal.bStartWithValidFrame=OMX_FALSE;
687 error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamBrcmVideoDecodeErrorConcealment,&conceal);
688 if (error!=OMX_ErrorNone){
689 Log::getInstance()->log("Video", Log::DEBUG, "OMX_IndexParamBrcmVideoDecodeErrorConcealment failed %x", error);
690 clock_mutex.Unlock();
691 DeAllocateCodecsOMX();
696 error=OMX_GetHandle(&omx_vid_sched,VPE_OMX_VIDEO_SCHED,NULL,&callbacks);
697 if (error!=OMX_ErrorNone){
698 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler failed %x", error);
699 clock_mutex.Unlock();
700 DeAllocateCodecsOMX();
706 error=OMX_GetParameter(omx_vid_sched,OMX_IndexParamVideoInit,&p_param);
707 if (error!=OMX_ErrorNone){
708 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler OMX_GetParameter failed %x", error);
709 clock_mutex.Unlock();
710 DeAllocateCodecsOMX();
713 omx_shed_input_port=p_param.nStartPortNumber;
714 omx_shed_output_port=p_param.nStartPortNumber+1;
717 error=OMX_GetParameter(omx_vid_sched,OMX_IndexParamOtherInit,&p_param);
718 if (error!=OMX_ErrorNone){
719 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler OMX_GetParameter failed %x", error);
720 clock_mutex.Unlock();
721 DeAllocateCodecsOMX();
724 omx_shed_clock_port=p_param.nStartPortNumber;
725 Log::getInstance()->log("Video", Log::DEBUG, "scheduler ports %d %d %d ",omx_shed_input_port,omx_shed_output_port,omx_shed_clock_port);
728 if (!DisablePort(omx_vid_sched,omx_shed_input_port,true) || !DisablePort(omx_vid_sched,omx_shed_output_port,true)
729 || !DisablePort(omx_vid_sched,omx_shed_clock_port,true)) {
730 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video shed failed");
731 clock_mutex.Unlock();
732 DeAllocateCodecsOMX();
737 error=OMX_GetHandle(&omx_vid_rend,VPE_OMX_VIDEO_REND,NULL,&callbacks);
738 if (error!=OMX_ErrorNone){
739 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video rend failed %x", error);
740 clock_mutex.Unlock();
741 DeAllocateCodecsOMX();
745 error=OMX_GetParameter(omx_vid_rend,OMX_IndexParamVideoInit,&p_param);
746 if (error!=OMX_ErrorNone){
747 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video rend OMX_GetParameter failed %x", error);
748 clock_mutex.Unlock();
749 DeAllocateCodecsOMX();
752 omx_rend_input_port=p_param.nStartPortNumber;
753 //omx_rend_output_port=p_param.nStartPortNumber+1;
756 if (!DisablePort(omx_vid_rend,omx_rend_input_port,true) /*|| !DisablePort(omx_vid_rend,omx_rend_output_port)*/
758 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video rend failed");
759 clock_mutex.Unlock();
760 DeAllocateCodecsOMX();
768 error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,omx_vid_sched,omx_shed_clock_port);
769 if (error!=OMX_ErrorNone){
770 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel clock to sched failed %x %d %d", error,omx_clock_output_port,omx_shed_clock_port);
771 clock_mutex.Unlock();
772 DeAllocateCodecsOMX();
776 if (!EnablePort(omx_clock,omx_clock_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_clock_port,false)
778 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX clock shed failed");
779 clock_mutex.Unlock();
780 DeAllocateCodecsOMX();
785 Log::getInstance()->log("Video", Log::DEBUG, "mark2 ");
786 if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) {
787 Log::getInstance()->log("Video", Log::DEBUG, "vid_sched idle ChangeComponentState");
788 clock_mutex.Unlock();
789 DeAllocateCodecsOMX();
795 Log::getInstance()->log("Video", Log::DEBUG, "mark1 ");
796 if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_clock_port)) {
797 clock_mutex.Unlock();
798 DeAllocateCodecsOMX();
805 Log::getInstance()->log("Video", Log::DEBUG, "mark1 special ");
806 if ( !CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port)) {
807 clock_mutex.Unlock();
808 DeAllocateCodecsOMX();
814 Log::getInstance()->log("Video", Log::DEBUG, "mark1b ");
817 /* error=OMX_SendCommand(omx_vid_dec,OMX_CommandStateSet,OMX_StateIdle,0);
818 if (error!=OMX_ErrorNone){
819 Log::getInstance()->log("Video", Log::DEBUG, "vid_dec Send Command to OMX State Idle %x", error);
823 OMX_VIDEO_PARAM_PORTFORMATTYPE ft_type;
824 memset(&ft_type,0,sizeof(ft_type));
825 ft_type.nSize=sizeof(ft_type);
826 ft_type.nVersion.nVersion=OMX_VERSION;
828 ft_type.nPortIndex=omx_codec_input_port;
830 ft_type.eCompressionFormat=OMX_VIDEO_CodingAVC;
832 ft_type.eCompressionFormat=OMX_VIDEO_CodingMPEG2;
835 Demuxer* demux=Demuxer::getInstance();
837 ft_type.xFramerate=0;//25*(1<<16);//demux->getFrameRate()*(1<<16);
838 Log::getInstance()->log("Video", Log::DEBUG, "Framerate: %d",demux->getFrameRate());
839 error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamVideoPortFormat,&ft_type);
840 if (error!=OMX_ErrorNone){
841 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexParamVideoPortFormat failed %x", error);
842 clock_mutex.Unlock();
843 DeAllocateCodecsOMX();
848 if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) {
849 Log::getInstance()->log("Video", Log::DEBUG, "vid_dec ChangeComponentState");
850 clock_mutex.Unlock();
851 DeAllocateCodecsOMX();
856 if (!PrepareInputBufsOMX()) {
857 clock_mutex.Unlock();
858 DeAllocateCodecsOMX();
863 error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,omx_vid_sched,omx_shed_input_port);
864 if (error!=OMX_ErrorNone){
865 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel dec to sched failed %x", error);
866 clock_mutex.Unlock();
867 DeAllocateCodecsOMX();
873 if (!EnablePort(omx_vid_dec,omx_codec_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_input_port,false)
875 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX codec shed failed");
876 clock_mutex.Unlock();
877 DeAllocateCodecsOMX();
881 if ( !CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_output_port) || !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_input_port)) {
882 clock_mutex.Unlock();
883 DeAllocateCodecsOMX();
887 if (!ChangeComponentState(omx_vid_dec,OMX_StateExecuting)) {
888 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_dec ChangeComponentState Execute");
889 clock_mutex.Unlock();
890 DeAllocateCodecsOMX();
894 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_output_port,omx_vid_rend,omx_rend_input_port);
895 if (error!=OMX_ErrorNone){
896 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel sched to rend failed %x", error);
897 clock_mutex.Unlock();
898 DeAllocateCodecsOMX();
902 if (!EnablePort(omx_vid_sched,omx_shed_output_port,false) || !EnablePort(omx_vid_rend,omx_rend_input_port,false)
904 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX shed rend failed");
905 clock_mutex.Unlock();
906 DeAllocateCodecsOMX();
910 if (!CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_output_port)
911 || !CommandFinished(omx_vid_rend,OMX_CommandPortEnable,omx_rend_input_port)) {
912 clock_mutex.Unlock();
913 DeAllocateCodecsOMX();
917 if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) {
918 Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState");
919 clock_mutex.Unlock();
920 DeAllocateCodecsOMX();
925 if (!ChangeComponentState(omx_vid_sched,OMX_StateExecuting)) {
926 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_sched ChangeComponentState Execute");
927 clock_mutex.Unlock();
928 DeAllocateCodecsOMX();
932 if (!ChangeComponentState(omx_vid_rend,OMX_StateExecuting)) {
933 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_rend ChangeComponentState Execute");
934 clock_mutex.Unlock();
935 DeAllocateCodecsOMX();
940 /*OMX_CONFIG_DISPLAYREGIONTYPE dispconf;
941 memset(&dispconf,0,sizeof(dispconf));
942 dispconf.nSize=sizeof(dispconf);
943 dispconf.nVersion.nVersion=OMX_VERSION;
945 dispconf.nPortIndex=omx_rend_input_port;
947 dispconf.set=OMX_DISPLAY_SET_LAYER ;
949 error=OMX_SetConfig(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
950 if (error!=OMX_ErrorNone){
951 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
952 clock_mutex.Unlock();
953 DeAllocateCodecsOMX();
957 /* dispconf.set=OMX_DISPLAY_SET_FULLSCREEN ;
958 dispconf.fullscreen=OMX_FALSE;
959 error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
960 if (error!=OMX_ErrorNone){
961 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
962 clock_mutex.Unlock();
963 DeAllocateCodecsOMX();
967 dispconf.set=OMX_DISPLAY_SET_DEST_RECT;
968 dispconf.dest_rect.x_offset=100;
969 dispconf.dest_rect.y_offset=100;
970 dispconf.dest_rect.width=640;
971 dispconf.dest_rect.height=480;
972 error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
973 if (error!=OMX_ErrorNone){
974 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
975 clock_mutex.Unlock();
976 DeAllocateCodecsOMX();
981 playbacktimeoffset=-GetCurrentSystemTime();
985 clock_mutex.Unlock();
989 setClockExecutingandRunning();
998 int VideoOMX::idleClock()
1000 OMX_ERRORTYPE error;
1001 OMX_STATETYPE temp_state;
1003 OMX_GetState(omx_clock,&temp_state);
1005 if (temp_state!=OMX_StateIdle) {
1006 if (!ChangeComponentState(omx_clock,OMX_StateIdle)) {
1007 Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Idle failed");
1008 clock_mutex.Unlock();
1012 clock_mutex.Unlock();
1016 int VideoOMX::setClockExecutingandRunning()
1018 OMX_ERRORTYPE error;
1019 OMX_STATETYPE temp_state;
1021 OMX_GetState(omx_clock,&temp_state);
1023 if (temp_state!=OMX_StateExecuting) {
1024 if (!ChangeComponentState(omx_clock,OMX_StateExecuting)) {
1025 Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Execute failed");
1026 clock_mutex.Unlock();
1027 DeAllocateCodecsOMX();
1032 OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
1033 memset(&clock_conf,0,sizeof(clock_conf));
1034 clock_conf.nSize=sizeof(clock_conf);
1035 clock_conf.nVersion.nVersion=OMX_VERSION;
1036 clock_conf.eState=OMX_TIME_ClockStateRunning;
1037 error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
1038 if (error!=OMX_ErrorNone) {
1039 Log::getInstance()->log("Video", Log::DEBUG, "Clock IndexConfigTimeClockState failed %x", error);
1040 clock_mutex.Unlock();
1041 DeAllocateCodecsOMX();
1044 clock_mutex.Unlock();
1050 int VideoOMX::ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type) //needs to be called with locked mutex
1052 OMX_ERRORTYPE error;
1053 error=OMX_SendCommand(handle,OMX_CommandStateSet,type,0);
1054 if (error!=OMX_ErrorNone){
1055 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to OMX State %x %x",handle,type, error);
1059 if (!CommandFinished(handle,OMX_CommandStateSet,type)) {
1067 int VideoOMX::EnablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait) //needs to be called with locked mutex
1069 OMX_ERRORTYPE error;
1070 error=OMX_SendCommand(handle,OMX_CommandPortEnable,port,0);
1071 if (error!=OMX_ErrorNone){
1072 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to enable port %x %x",handle,port, error);
1076 if (!wait) return 1;
1077 if (!CommandFinished(handle,OMX_CommandPortEnable,port)) {
1085 int VideoOMX::DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait) //needs to be called with locked mutex
1087 OMX_ERRORTYPE error;
1088 error=OMX_SendCommand(handle,OMX_CommandPortDisable,port,0);
1089 if (error!=OMX_ErrorNone){
1090 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to disable port %x %x",handle,port, error);
1094 if (!wait) return 1;
1095 if (!CommandFinished(handle,OMX_CommandPortDisable,port)) {
1106 int VideoOMX::CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2) //needs to be called with locked mutex
1110 omx_event_mutex.Lock();
1111 list<VPE_OMX_EVENT>::iterator itty=omx_events.begin();
1112 while (itty!=omx_events.end()) {
1114 VPE_OMX_EVENT current=*itty;
1115 if (current.handle==handle) { //this is ours
1116 if (current.event_type==OMX_EventError) {
1117 omx_events.erase(itty);
1118 omx_event_mutex.Unlock();
1119 Log::getInstance()->log("Video", Log::DEBUG, "Command Finished on Error");
1122 } else if (current.event_type==OMX_EventCmdComplete && current.data1==command && current.data2==data2) {
1123 omx_events.erase(itty);
1124 omx_event_mutex.Unlock();
1125 //Log::getInstance()->log("Video", Log::DEBUG, "Command Finished Completed");
1132 omx_event_mutex.Unlock();
1137 Log::getInstance()->log("Video", Log::DEBUG, "CommandFinished waited too long %x %x %x",handle,command, data2);
1146 int VideoOMX::PrepareInputBufsOMX() //needs to be called with locked mutex
1148 OMX_ERRORTYPE error;
1149 OMX_PARAM_PORTDEFINITIONTYPE port_def_type;
1150 memset(&port_def_type,0,sizeof(port_def_type));
1151 port_def_type.nSize=sizeof(port_def_type);
1152 port_def_type.nVersion.nVersion=OMX_VERSION;
1153 port_def_type.nPortIndex=omx_codec_input_port;
1155 error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type);
1157 if (error!=OMX_ErrorNone){
1158 Log::getInstance()->log("Video", Log::DEBUG, "Get OMX OMX_IndexParamPortDefinition failed %x", error);
1160 /* Log::getInstance()->log("Video", Log::DEBUG, "Port para %d %d %d %d %d %d %d", port_def_type.nBufferCountActual,
1161 port_def_type.nBufferCountMin,port_def_type.nBufferSize,port_def_type.bEnabled,port_def_type.bPopulated,
1162 port_def_type.bBuffersContiguous,port_def_type.nBufferAlignment);*/
1164 port_def_type.nBufferCountActual=100;
1165 port_def_type.nBufferSize=max(port_def_type.nBufferSize,200000); // for transcoder important
1167 error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type);
1169 if (error!=OMX_ErrorNone){
1170 Log::getInstance()->log("Video", Log::DEBUG, "Set OMX OMX_IndexParamPortDefinition failed %x", error);
1174 error=OMX_SendCommand(omx_vid_dec,OMX_CommandPortEnable,omx_codec_input_port,0);
1175 if (error!=OMX_ErrorNone){
1176 Log::getInstance()->log("Video", Log::DEBUG, "Prepare Input bufs Send Command to enable port %x", error);
1180 input_bufs_omx_mutex.Lock();
1181 for (unsigned int i=0; i< port_def_type.nBufferCountActual;i++) {
1183 // unsigned char* new_buffer_data=(unsigned char*)malloc(port_def_type.nbufferSize);
1184 OMX_BUFFERHEADERTYPE *buf_head=NULL;
1185 /* error=OMX_Usebuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nbufferSize,new_buffer_data);
1186 if (error!=OMX_ErrorNone){
1187 Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_Usebuffer failed %x", error);
1188 input_bufs_omx_mutex.Unlock();
1191 error=OMX_AllocateBuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nBufferSize);
1192 if (error!=OMX_ErrorNone){
1193 Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_AllocateBuffer failed %x", error);
1194 input_bufs_omx_mutex.Unlock();
1197 input_bufs_omx_all.push_back(buf_head);
1198 input_bufs_omx_free.push_back(buf_head);
1200 omx_first_frame=true;
1203 cur_input_buf_omx=NULL;
1204 input_bufs_omx_mutex.Unlock();
1207 Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark3");
1208 if (!CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_input_port)) {
1211 Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark4");
1216 int VideoOMX::DestroyInputBufsOMX() //need s to be called with locked mutex
1218 OMX_ERRORTYPE error;
1220 cur_input_buf_omx=NULL;
1221 input_bufs_omx_mutex.Lock();
1222 for (int i=0; i< input_bufs_omx_all.size();i++) {
1223 // free(input_bufs_omx_all[i]->pBuffer);
1224 // input_bufs_omx_all[i]->pBuffer=NULL;
1225 error=OMX_FreeBuffer(omx_vid_dec,omx_codec_input_port,input_bufs_omx_all[i]);
1226 if (error!=OMX_ErrorNone){
1227 Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_FreeBuffer failed %x", error);
1228 input_bufs_omx_mutex.Unlock();
1233 input_bufs_omx_all.clear();
1234 input_bufs_omx_free.clear();
1235 input_bufs_omx_present.clear();
1236 input_time_present.clear();
1237 input_bufs_omx_mutex.Unlock();
1244 int VideoOMX::DeAllocateCodecsOMX()
1246 OMX_ERRORTYPE error;
1248 Log::getInstance()->log("Video", Log::DEBUG, "enter deallocatecodecsomx");
1252 if (cur_input_buf_omx) {
1253 cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_EOS;
1254 OMX_ERRORTYPE error=ProtOMXEmptyThisBuffer(omx_vid_dec,cur_input_buf_omx);
1255 if (error!=OMX_ErrorNone) {
1256 Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error);
1259 cur_input_buf_omx=NULL;//write out old data
1263 // first stop the omx elements
1264 if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) {
1265 Log::getInstance()->log("Video", Log::DEBUG, "vid_dec ChangeComponentState");
1268 clock_mutex.Unlock();
1274 if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) {
1275 Log::getInstance()->log("Video", Log::DEBUG, "vid_shed ChangeComponentState");
1279 if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) {
1280 Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState");
1286 // TODO proper deinit sequence
1287 // first flush all buffers
1290 error = OMX_SendCommand(omx_vid_dec, OMX_CommandFlush,
1291 omx_codec_output_port, NULL);
1292 if (error != OMX_ErrorNone) {
1293 Log::getInstance()->log("Video", Log::DEBUG,
1294 "OMX_Flush codec out failed %x", error);
1298 error = OMX_SendCommand(omx_vid_sched, OMX_CommandFlush,
1299 omx_shed_input_port, NULL);
1300 if (error != OMX_ErrorNone) {
1301 Log::getInstance()->log("Video", Log::DEBUG,
1302 "OMX_Flush shed in failed %x", error);
1306 if (!CommandFinished(omx_vid_dec, OMX_CommandFlush,
1307 omx_codec_output_port)) {
1308 Log::getInstance()->log("Video", Log::DEBUG,
1309 "flush cmd codec failed");
1312 if (!CommandFinished(omx_vid_sched, OMX_CommandFlush,
1313 omx_shed_input_port)) {
1314 Log::getInstance()->log("Video", Log::DEBUG,
1315 "flush cmd shed failed");
1321 error = OMX_SendCommand(omx_vid_rend, OMX_CommandFlush,
1322 omx_rend_input_port, NULL);
1323 if (error != OMX_ErrorNone) {
1324 Log::getInstance()->log("Video", Log::DEBUG,
1325 "OMX_Flush rend in failed %x", error);
1329 error = OMX_SendCommand(omx_vid_sched, OMX_CommandFlush,
1330 omx_shed_output_port, NULL);
1331 if (error != OMX_ErrorNone) {
1332 Log::getInstance()->log("Video", Log::DEBUG,
1333 "OMX_Flush shed out failed %x", error);
1339 if (!CommandFinished(omx_vid_rend, OMX_CommandFlush,
1340 omx_rend_input_port)) {
1341 Log::getInstance()->log("Video", Log::DEBUG,
1342 "flush cmd shed rend failed");
1345 if (!CommandFinished(omx_vid_sched, OMX_CommandFlush,
1346 omx_shed_output_port)) {
1347 Log::getInstance()->log("Video", Log::DEBUG,
1348 "flush cmd shed rend failed");
1355 error=OMX_SendCommand(omx_clock,OMX_CommandFlush, omx_clock_output_port, NULL);
1356 if (error!=OMX_ErrorNone){
1357 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush clock out failed %x", error);
1361 error=OMX_SendCommand(omx_vid_sched,OMX_CommandFlush, omx_shed_clock_port, NULL);
1362 if (error!=OMX_ErrorNone){
1363 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush shed clock failed %x", error);
1367 if (!CommandFinished(omx_clock,OMX_CommandFlush,omx_clock_output_port) ||
1368 !CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_clock_port)) {
1369 Log::getInstance()->log("Video", Log::DEBUG, "flush cmd clock shed failed");
1375 error = OMX_SendCommand(omx_vid_dec, OMX_CommandFlush,
1376 omx_codec_input_port, NULL);
1377 if (error != OMX_ErrorNone) {
1378 Log::getInstance()->log("Video", Log::DEBUG,
1379 "OMX_Flush codec out failed %x", error);
1386 DestroyInputBufsOMX();
1389 if (!DisablePort(omx_vid_sched,omx_shed_output_port,true)) {
1390 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 2 ");
1392 if (!DisablePort(omx_vid_rend,omx_rend_input_port,true)) {
1393 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 1");
1399 if (!DisablePort(omx_vid_dec,omx_codec_output_port,true)) {
1400 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 6");
1405 if (!DisablePort(omx_vid_dec,omx_codec_input_port,true)) {
1406 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 7");
1412 if (!DisablePort(omx_vid_sched,omx_shed_input_port,true)) {
1413 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 3");
1416 if (!DisablePort(omx_vid_sched,omx_shed_clock_port,true)) {
1417 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 4");
1420 if (!DisablePort(omx_clock,omx_clock_output_port,true)) {
1421 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 5");
1427 error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,NULL,NULL);
1428 if (error!=OMX_ErrorNone) {
1429 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1433 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_input_port,NULL,NULL);
1434 if (error!=OMX_ErrorNone) {
1435 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1440 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_output_port,NULL,NULL);
1441 if (error!=OMX_ErrorNone) {
1442 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1446 error=OMX_SetupTunnel(omx_vid_rend,omx_rend_input_port,NULL,NULL);
1447 if (error!=OMX_ErrorNone) {
1448 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1453 error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,NULL,NULL);
1454 if (error!=OMX_ErrorNone) {
1455 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1459 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_clock_port,NULL,NULL);
1460 if (error!=OMX_ErrorNone) {
1461 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1468 error=OMX_FreeHandle(omx_vid_dec);
1469 error=OMX_FreeHandle(omx_vid_sched);
1470 error=OMX_FreeHandle(omx_vid_rend);
1472 clock_mutex.Unlock();
1474 if (error!=OMX_ErrorNone) {
1475 Log::getInstance()->log("Video", Log::DEBUG, "FreeHandle failed %d", error);
1477 } else clock_mutex.Unlock();
1478 Log::getInstance()->log("Video", Log::DEBUG, "leave deallocate codecs OMX");
1484 void VideoOMX::destroyClock()
1487 if (clock_references>0) {
1489 if (clock_references==0) {
1490 OMX_ERRORTYPE error;
1491 Log::getInstance()->log("Video", Log::DEBUG, "destroy omx clock");
1492 error=OMX_FreeHandle(omx_clock);
1493 if (error!=OMX_ErrorNone) {
1494 Log::getInstance()->log("Video", Log::DEBUG, "FreeHandle failed %d", error);
1499 clock_mutex.Unlock();
1503 int VideoOMX::stop()
1505 if (!initted) return 0;
1508 //Check if libav mode
1509 DeAllocateCodecsOMX();
1514 // if (ioctl(fdVideo, AV_SET_VID_STOP, 0) != 0) return 0;
1518 int VideoOMX::reset()
1520 if (!initted) return 0;
1523 DeAllocateCodecsOMX();
1524 // if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0;
1528 int VideoOMX::pause()
1530 if (!initted) return 0;
1531 Log::getInstance()->log("Video", Log::DEBUG, "enter pause");
1534 //maybe also change omx clock?
1535 pausetimecode=GetCurrentSystemTime();
1541 int VideoOMX::unPause() // FIXME get rid - same as play!! Not here!
1543 if (!initted) return 0;
1544 Log::getInstance()->log("Video", Log::DEBUG, "enter unpause");
1547 playbacktimeoffset+=GetCurrentSystemTime()-pausetimecode;
1548 paused=false; // may be also change omx clock
1554 int VideoOMX::fastForward()
1556 if (!initted) return 0;
1558 // if (ioctl(fdVideo, AV_SET_VID_libavWD, 1) != 0) return 0;
1562 int VideoOMX::unFastForward()
1564 if (!initted) return 0;
1566 // if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; // don't need this.
1568 //// if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
1572 int VideoOMX::attachFrameBuffer()
1574 if (!initted) return 0;
1576 // if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
1580 int VideoOMX::blank(void)
1582 // if (ioctl(fdVideo, AV_SET_VID_FB, 1) != 0) return 0;
1583 // if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
1587 ULLONG VideoOMX::getCurrentTimestamp()
1589 if (iframemode) return 0;
1590 return lastreftimePTS;
1595 ULONG VideoOMX::timecodeToFrameNumber(ULLONG timecode)
1597 if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
1598 else return (ULONG)(((double)timecode / (double)90000) * (double)30);
1603 int VideoOMX::test()
1608 // return ioctl(fdVideo, AV_SET_VID_STC, &stc);
1615 int VideoOMX::test2()
1623 long long VideoOMX::SetStartOffset(long long curreftime, bool *rsync)
1627 startoffset=curreftime;//offset is set for audio
1629 offsetvideonotset=false;
1631 if (offsetvideonotset) {
1632 offsetvideonotset=false;
1635 if ( (curreftime-lastrefvideotime)>10000000LL
1636 || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync
1637 startoffset+=curreftime-lastrefvideotime;
1638 lastrefaudiotime+=curreftime-lastrefvideotime;
1640 offsetaudionotset=true;
1647 lastrefvideotime=curreftime;
1653 long long VideoOMX::SetStartAudioOffset(long long curreftime, bool *rsync)
1657 startoffset=curreftime;
1659 offsetaudionotset=false;
1661 if (offsetaudionotset) {
1662 offsetaudionotset=false;
1665 if ( (curreftime-lastrefaudiotime)>10000000LL
1666 || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync
1667 startoffset+=curreftime-lastrefaudiotime;
1668 lastrefvideotime+=curreftime-lastrefaudiotime;
1670 offsetvideonotset=true;
1676 lastrefaudiotime=curreftime;
1681 void VideoOMX::ResetTimeOffsets() {
1682 offsetnotset=true; //called from demuxer
1683 offsetvideonotset=true;
1684 offsetaudionotset=true;
1692 long long VideoOMX::GetCurrentSystemTime()
1695 clock_gettime(CLOCK_MONOTONIC, &ts);
1696 return ts.tv_sec*10000000LL+ts.tv_nsec/100LL;
1699 void VideoOMX::WaitUntil(long long time)
1701 struct timespec interval;
1702 interval.tv_sec=time/10000000LL;
1703 interval.tv_nsec=(time %10000000LL)*100LL;
1704 while (clock_nanosleep(CLOCK_MONOTONIC,TIMER_ABSTIME,&interval,NULL)==EINTR) {
1705 //Log::getInstance()->log("Video", Log::DEBUG, "Wait until multi");
1710 bool VideoOMX::FrameSkip(long long pts)
1712 //ok first calculate the absolute time
1714 long long target_time=pts-playbacktimeoffset;
1715 // we have to wait untile the next frame
1716 long long offset=Demuxer::getInstance()->getFrameRate();
1717 if (offset==0) offset=25;
1718 offset=-2*10000000LL/offset;
1719 target_time+=offset;
1720 long long current_time=GetCurrentSystemTime();
1722 if ((target_time-current_time)<-400000LL) {
1723 skip=true; // we are too slow
1725 /* Log::getInstance()->log("Video", Log::DEBUG,
1726 "Skipping frames1 %lld %lld",target_time-current_time,pts);
1727 Log::getInstance()->log("Video", Log::DEBUG, "skip detail pts: %lld target: %lld sys: %lld off: %lld diff %lld",pts,target_time,current_time,offset,
1728 target_time-current_time);*/
1733 if ((target_time - current_time) < 0000LL) { //skip a bit more
1734 skip = true; // we are too slow
1736 /* Log::getInstance()->log("Video", Log::DEBUG,"Skipping frames2 %lld %lld",target_time-current_time,pts);
1737 Log::getInstance()->log("Video", Log::DEBUG, "skip detail pts: %lld target: %lld sys: %lld off: %lld diff %lld",pts,target_time,current_time,offset,
1738 target_time-current_time);*/
1748 void VideoOMX::FrameWaitforDisplay(long long pts)
1750 //ok first calculate the absolute time
1751 long long target_time=pts-playbacktimeoffset;
1752 // we have to wait untile the next frame
1753 long long offset=Demuxer::getInstance()->getFrameRate();
1754 long long current_time=GetCurrentSystemTime();
1755 if (offset==0) offset=25;
1756 offset=-2*10000000LL/offset;
1757 target_time+=offset;
1758 if ((target_time-current_time)>1000000LL) target_time=current_time+1000000LL; // something is wrong do not wait too long
1759 //Log::getInstance()->log("Video", Log::DEBUG, "Wait for display pts: %lld target: %lld sys: %lld off: %lld diff %lld",pts,target_time,current_time,offset,
1760 // target_time-current_time);
1762 WaitUntil(target_time);
1763 //Log::getInstance()->log("Video", Log::DEBUG, "Wait for display out %lld",GetCurrentSystemTime());
1766 void VideoOMX::AdjustAudioPTS(long long pts)
1768 long long newplaybacktimeoffset=pts-GetCurrentSystemTime();
1769 /* if ((newplaybacktimeoffset-1000000LL)>playbacktimeoffset
1770 || (newplaybacktimeoffset+1000000LL)<playbacktimeoffset) {
1771 Log::getInstance()->log("Video", Log::DEBUG, "Adjust Playbackoffsettime o: %lld n: %lld",
1772 playbacktimeoffset,newplaybacktimeoffset);*/
1773 playbacktimeoffset=newplaybacktimeoffset;
1778 void VideoOMX::threadPostStopCleanup()
1782 Log::getInstance()->log("Video", Log::DEBUG,
1787 void VideoOMX::threadMethod()
1789 Log::getInstance()->log("Video", Log::DEBUG,
1793 OMX_BUFFERHEADERTYPE* pict=NULL;
1796 input_bufs_omx_mutex.Lock();
1797 if (input_bufs_omx_present.size()>0) {
1799 pict=input_bufs_omx_present.front();
1800 time=input_time_present.front();
1801 input_bufs_omx_present.pop_front();
1802 input_time_present.pop_front();
1804 input_bufs_omx_mutex.Unlock();
1808 //Log::getInstance()->log("Video", Log::DEBUG,
1810 if (time!=0 &&FrameSkip(time) && !(pict->nFlags &OMX_BUFFERFLAG_STARTTIME)) {
1812 input_bufs_omx_mutex.Lock();
1813 input_bufs_omx_free.push_back(pict);
1814 input_bufs_omx_mutex.Unlock();
1817 OMX_ERRORTYPE error = ProtOMXEmptyThisBuffer(omx_vid_dec, pict);
1818 if (error != OMX_ErrorNone) {
1819 Log::getInstance()->log("Video", Log::DEBUG,
1820 "OMX_EmptyThisBuffer failed %x", error);
1822 if (time!=0) FrameWaitforDisplay(time);
1830 Log::getInstance()->log("Video", Log::DEBUG,
1834 void VideoOMX::PutBufferToPres(OMX_BUFFERHEADERTYPE* buffer, long long time)
1836 input_bufs_omx_mutex.Lock();
1837 input_bufs_omx_present.push_back(buffer);
1838 input_time_present.push_back(time);
1839 input_bufs_omx_mutex.Unlock();
1843 OMX_ERRORTYPE VideoOMX::ProtOMXEmptyThisBuffer(OMX_HANDLETYPE handle, OMX_BUFFERHEADERTYPE* buffer)
1845 // protect the call to empty this buffer
1848 pthread_testcancel();
1849 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldcancelstate);
1850 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldcanceltype);
1852 OMX_ERRORTYPE ret_val;
1853 ret_val=OMX_EmptyThisBuffer(handle,buffer);
1854 clock_mutex.Unlock();
1855 pthread_setcancelstate(oldcancelstate, NULL);
1856 pthread_setcanceltype(oldcanceltype, NULL);
1857 pthread_testcancel();
1861 void VideoOMX::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
1863 mediapacket = mplist.front();
1866 UINT VideoOMX::DeliverMediaSample(UCHAR* buffer, UINT *samplepos)
1868 DeliverMediaPacket(mediapacket, buffer, samplepos);
1869 if (*samplepos == mediapacket.length) {
1876 UINT VideoOMX::DeliverMediaPacket(MediaPacket packet,
1877 const UCHAR* buffer,
1880 if (packet.type == MPTYPE_VIDEO_H264)
1890 //Later add fail back code for libav
1892 *samplepos+=packet.length;
1893 return packet.length;
1897 if (!omx_running) return 0; // if we are not runnig do not do this
1898 if (paused) return 0; //Block if we pause
1900 long long current_media_time=GetCurrentSystemTime()+playbacktimeoffset;
1901 /* if (packet.synched &&
1902 (packet.presentation_time<0 /*|| // preroll skip frames
1903 (packet.presentation_time+5000000LL)<(current_media_time)*)) { // we are late skip
1904 Log::getInstance()->log("Video", Log::DEBUG, "DeliverMediaPacketOMX Preroll or too late %lld %lld; %lld", packet.presentation_time,current_media_time,playbacktimeoffset);
1905 *samplepos=packet.length;
1906 return packet.length;
1909 OMX_ERRORTYPE error;
1911 /*First Check, if we have an video sample*/
1915 return 0; //Not in iframe mode!
1919 if (packet.disconti) {
1921 if (cur_input_buf_omx) {
1922 PutBufferToPres(cur_input_buf_omx, lastreftimeOMX);
1923 cur_input_buf_omx=NULL;
1927 /*Inspect PES-Header */
1929 // OMX_STATETYPE temp_state;
1930 // OMX_GetState(omx_vid_dec,&temp_state);
1932 if (*samplepos==0) {//stripheader
1933 headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
1934 // if (h264) Log::getInstance()->log("Video", Log::DEBUG, "PES info %x %x %x %x",
1935 // buffer[packet.pos_buffer+0],buffer[packet.pos_buffer+1],buffer[packet.pos_buffer+2],buffer[packet.pos_buffer+3]);
1936 *samplepos+=headerstrip;
1937 if ( packet.synched ) {
1938 if (cur_input_buf_omx) {
1939 cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_ENDOFFRAME;
1940 PutBufferToPres(cur_input_buf_omx, lastreftimeOMX);
1941 cur_input_buf_omx=NULL;//write out old data
1947 if (!firstsynched) {//
1948 *samplepos=packet.length;//if we have not processed at least one
1949 return packet.length;//synched packet ignore it!
1954 if (!cur_input_buf_omx) {
1955 input_bufs_omx_mutex.Lock();
1956 if (input_bufs_omx_free.size()==0) {
1957 input_bufs_omx_mutex.Unlock();
1958 //Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket no free sample");
1959 return 0; // we do not have a free media sample
1962 cur_input_buf_omx=input_bufs_omx_free.front();
1963 cur_input_buf_omx->nFilledLen=0;
1964 cur_input_buf_omx->nOffset=0;
1965 cur_input_buf_omx->nTimeStamp=0;
1966 input_bufs_omx_free.pop_front();
1967 input_bufs_omx_mutex.Unlock();
1973 if (cur_input_buf_omx->nFilledLen==0) {//will only be changed on first packet
1974 if (packet.synched) {
1975 // Log::getInstance()->log("Video", Log::DEBUG, "packet synched marker");
1977 //lastreftimePTS=packet.pts;
1978 if (omx_first_frame) { // TODO time
1979 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_STARTTIME;
1980 Log::getInstance()->log("Video", Log::DEBUG, "Starttime");
1981 omx_first_frame=false;
1983 //cur_input_buf_omx->nFlags=0;
1984 cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_TIME_UNKNOWN;
1986 lastreftimeOMX=packet.presentation_time;
1987 // Log::getInstance()->log("Video", Log::DEBUG, "Time code %lld pts %lld", lastreftimeOMX,packet.pts);
1988 lastreftimePTS=packet.pts;
1989 cur_input_buf_omx->nTimeStamp=0;//lastreftimeOMX; // the clock component is faulty;
1993 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
1994 cur_input_buf_omx->nTimeStamp=0;
1997 // ms->SetSyncPoint(TRUE);
1999 if (packet.disconti) cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_DISCONTINUITY;
2004 unsigned int haveToCopy=packet.length-*samplepos;
2006 while (haveToCopy> (cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen)) {
2007 unsigned int cancopy=cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen;
2008 memcpy(cur_input_buf_omx->pBuffer+cur_input_buf_omx->nFilledLen,buffer+packet.pos_buffer+*samplepos,cancopy);
2009 haveToCopy-=cancopy;
2010 cur_input_buf_omx->nFilledLen+=cancopy;
2011 *samplepos+=cancopy;
2012 // push old buffer out
2014 PutBufferToPres(cur_input_buf_omx, 0LL);
2016 input_bufs_omx_mutex.Lock();
2017 if (input_bufs_omx_free.size()==0) {
2018 input_bufs_omx_mutex.Unlock();
2019 //Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket no free sample");
2020 return *samplepos; // we do not have a free media sample
2022 cur_input_buf_omx=input_bufs_omx_free.front();
2023 cur_input_buf_omx->nFilledLen=0;
2024 cur_input_buf_omx->nOffset=0;
2025 cur_input_buf_omx->nTimeStamp=0;
2026 input_bufs_omx_free.pop_front();
2027 input_bufs_omx_mutex.Unlock();
2029 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
2032 memcpy(cur_input_buf_omx->pBuffer+cur_input_buf_omx->nFilledLen,
2033 buffer+packet.pos_buffer+*samplepos,haveToCopy);
2034 cur_input_buf_omx->nFilledLen+=haveToCopy;
2038 *samplepos+=haveToCopy;
2047 bool VideoOMX::displayIFrame(const UCHAR* buffer, UINT length) {
2048 if (!omx_running) return false;
2050 EnterIframePlayback();
2052 int haveToCopy = length;
2054 if (!cur_input_buf_omx) {
2055 input_bufs_omx_mutex.Lock();
2056 if (input_bufs_omx_free.size() == 0) {
2057 input_bufs_omx_mutex.Unlock();
2058 // Log::getInstance()->log("Video", Log::DEBUG,
2059 // "Deliver MediaPacket no free sample");
2060 return false; // we do not have a free media sample
2063 cur_input_buf_omx = input_bufs_omx_free.front();
2064 cur_input_buf_omx->nFilledLen = 0;
2065 cur_input_buf_omx->nOffset = 0;
2066 cur_input_buf_omx->nTimeStamp = 0;
2067 input_bufs_omx_free.pop_front();
2068 input_bufs_omx_mutex.Unlock();
2072 unsigned int pattern, packet_length;
2073 unsigned int headerstrip = 0;
2078 //Now we strip the pes header
2079 pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);
2080 while (read_pos + 7 <= length) {
2081 pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos + 3];
2082 if (pattern < 0x000001E0 || pattern > 0x000001EF) {
2086 headerstrip = buffer[read_pos + 8] + 9/*is this right*/;
2087 packet_length = ((buffer[read_pos + 4] << 8)
2088 | (buffer[read_pos + 5])) + 6;
2089 if (read_pos + packet_length > length)
2092 if ((headerstrip < packet_length)
2093 && (cur_input_buf_omx->nFilledLen + packet_length
2094 - headerstrip) > cur_input_buf_omx->nAllocLen) {
2096 cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_STARTTIME;
2099 cur_input_buf_omx->nFlags
2100 |= OMX_BUFFERFLAG_TIME_UNKNOWN;
2103 cur_input_buf_omx->nTimeStamp = 0;
2104 PutBufferToPres(cur_input_buf_omx, 0);
2105 cur_input_buf_omx = NULL;
2107 if (!cur_input_buf_omx) {
2109 while (count < 100 && omx_running && iframemode) {
2112 input_bufs_omx_mutex.Lock();
2113 if (input_bufs_omx_free.size() == 0) {
2114 input_bufs_omx_mutex.Unlock();
2115 // Log::getInstance()->log("Video", Log::DEBUG,
2116 // "Ifrane no free sample");
2118 if (!omx_running) return false;
2121 cur_input_buf_omx = input_bufs_omx_free.front();
2122 cur_input_buf_omx->nFilledLen = 0;
2123 cur_input_buf_omx->nOffset = 0;
2124 cur_input_buf_omx->nTimeStamp = 0;
2125 input_bufs_omx_free.pop_front();
2126 input_bufs_omx_mutex.Unlock();
2129 if (!cur_input_buf_omx)
2134 if (packet_length > headerstrip) {
2136 cur_input_buf_omx->pBuffer
2137 + cur_input_buf_omx->nFilledLen,
2138 buffer + read_pos + headerstrip,
2139 packet_length - headerstrip);
2140 cur_input_buf_omx->nFilledLen += packet_length
2143 read_pos += packet_length;
2145 pattern = (buffer[read_pos] << 16)
2146 | (buffer[read_pos + 1] << 8) | (buffer[read_pos + 2]);
2152 cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_STARTTIME;
2155 cur_input_buf_omx->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
2158 cur_input_buf_omx->nTimeStamp = 0;
2159 PutBufferToPres(cur_input_buf_omx, 0);
2160 cur_input_buf_omx = NULL;
2163 MILLISLEEP(40); //Block a bit
2167 int VideoOMX::EnterIframePlayback()
2170 if (cur_input_buf_omx) {
2171 PutBufferToPres(cur_input_buf_omx, lastreftimeOMX);
2173 cur_input_buf_omx = NULL;
2175 clock_mutex.Unlock();