]> git.vomp.tv Git - vompclient.git/blob - videoomx.cc
Switch to OpenVG based OSD, note Teletext and Subtitle rendering not working and...
[vompclient.git] / videoomx.cc
1 /*
2     Copyright 2004-2005 Chris Tallon, 2009 Marten Richter
3
4     This file is part of VOMP.
5
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.
10
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.
15
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.
19 */
20
21 #include "videoomx.h"
22 #include "audioomx.h"
23 #include "mtdraspberry.h"
24 #include "demuxer.h"
25 #include "vdr.h"
26 #include "woptionpane.h"
27 #include "osdopenvg.h"
28
29
30 // temp
31 #include "log.h"
32
33 //A lot of parts of this file are heavily inspired by xbmc omx implementations
34
35 VideoOMX::VideoOMX() {
36
37         omx_running = false;
38
39         omx_vid_dec = 0;
40         cur_input_buf_omx = NULL;
41         omx_h264 = omx_mpeg2 = true;
42         clock_references = 0;
43
44         offsetnotset = true;
45         offsetvideonotset = true;
46         offsetaudionotset = true;
47         startoffset = 0;
48         lastrefaudiotime = 0;
49         lastrefvideotime = 0;
50         lastreftimeOMX = 0;
51         lastreftimePTS = 0;
52         firstsynched = false;
53
54         mode=NORMAL;
55         xpos=ypos=0.f;
56         deinterlace=2; //advanced
57
58 }
59
60 VideoOMX::~VideoOMX()
61 {
62   instance = NULL;
63 }
64
65 int VideoOMX::init(UCHAR tformat)
66 {
67   if (initted) return 0;
68   initted = 1;
69
70   if (!setFormat(tformat))           { shutdown(); return 0; }
71   if (!setConnection(COMPOSITERGB))  { shutdown(); return 0; }
72   if (!setAspectRatio(ASPECT4X3))    { shutdown(); return 0; }
73   if (!setMode(NORMAL))              { shutdown(); return 0; }
74   if (!setSource())                  { shutdown(); return 0; }
75   if (!attachFrameBuffer())          { shutdown(); return 0; }
76
77   setTVsize(ASPECT4X3);
78
79
80
81
82
83   //stop();
84
85
86
87   return 1;
88 }
89
90 int VideoOMX::initUsingOSDObjects()
91 {
92
93 // we are called before the audio
94         OMX_ERRORTYPE error;
95         error=OMX_Init();
96         if (error!=OMX_ErrorNone) {
97                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX failed %x", error);
98                 return 0;
99         }
100
101         return 1;
102 }
103
104
105 OMX_ERRORTYPE VideoOMX::EventHandler_OMX(OMX_IN OMX_HANDLETYPE handle,OMX_IN OMX_PTR appdata,
106            OMX_IN OMX_EVENTTYPE event_type,OMX_IN OMX_U32 data1,
107            OMX_IN OMX_U32 data2,OMX_IN OMX_PTR event_data) {
108
109         Log::getInstance()->log("Video", Log::NOTICE, "eventHandler %x %x %x %x %x",handle,event_type,data1,data2,event_data);
110
111         struct VPE_OMX_EVENT  new_event;
112         new_event.handle=handle;
113         new_event.appdata=appdata;
114         new_event.event_type=event_type;
115         new_event.data1=data1;
116         new_event.data2=data2;
117         new_event.event_data=event_data;
118
119         VideoOMX *video=(VideoOMX *)getInstance();
120         video->AddOmxEvent(new_event);
121
122 /*      switch (event_type) {
123         case OMX_EventCmdComplete: {
124
125         } break;
126         }*/
127
128         return OMX_ErrorNone;
129
130 }
131
132 void VideoOMX::AddOmxEvent(VPE_OMX_EVENT  new_event)
133 {
134         omx_event_mutex.Lock();
135     omx_events.push_back(new_event);
136         omx_event_mutex.Unlock();
137 }
138
139
140 OMX_ERRORTYPE VideoOMX::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer){
141
142         //Log::getInstance()->log("Video", Log::NOTICE, "EmptyBufferDone");
143         VideoOMX *video=(VideoOMX *)getInstance();
144         video->ReturnEmptyOMXBuffer(buffer);
145         return OMX_ErrorNone;
146
147 }
148
149 void VideoOMX::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){
150         input_bufs_omx_mutex.Lock();
151         //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());
152         input_bufs_omx_free.push_back(buffer);
153         //Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size());
154         input_bufs_omx_mutex.Unlock();
155 }
156
157  OMX_ERRORTYPE VideoOMX::FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer) {
158          Log::getInstance()->log("Video", Log::NOTICE, "FillBufferDone");
159         return OMX_ErrorNone;
160 }
161
162
163
164 int VideoOMX::shutdown()
165 {
166   if (!initted) return 0;
167   initted = 0;
168
169   DeAllocateCodecsOMX();
170   OMX_Deinit();
171   vc_tv_show_info(0); // back to console
172   return 1;
173 }
174
175
176
177 bool VideoOMX::loadOptionsfromServer(VDR* vdr)
178 {
179         Log::getInstance()->log("Video", Log::DEBUG, "VideoOMX config load");
180     char *name=vdr->configLoad("VideoOMX","SDDeinterlacing");
181
182     if (name != NULL) {
183                 if (STRCASECMP(name, "None") == 0) {
184                         deinterlace = 0;
185                 }/* else if (STRCASECMP(name, "LineDouble") == 0) {
186                         deinterlace = 1;
187                 }*/ else if (STRCASECMP(name, "Advanced") == 0) {
188                         deinterlace = 2;
189                 } /*else if (STRCASECMP(name, "Crazy") == 0) {
190                         deinterlace = 3; // this does not activate deinterlacing but a image filter, just for fun
191                 }*/
192                 Log::getInstance()->log("Video", Log::DEBUG, "Set deinterlacing to %s %d",name,deinterlace);
193         }
194
195    return true;
196
197 }
198
199 bool VideoOMX::handleOptionChanges(Option* option)
200 {
201     if (Video::handleOptionChanges(option))
202                 return true;
203         switch (option->id) {
204         case 1: {
205                 if (STRCASECMP(option->options[option->userSetChoice], "None") == 0) {
206                         deinterlace = 0;
207                 } /*else if (STRCASECMP(option->options[option->userSetChoice], "LineDouble")
208                                 == 0) {
209                         deinterlace = 1;
210                 }*/ else if (STRCASECMP(option->options[option->userSetChoice], "Advanced")
211                                 == 0) {
212                         deinterlace = 2;
213                 } /*else if (STRCASECMP(option->options[option->userSetChoice], "Crazy")
214                                 == 0) {
215                         deinterlace = 3;
216                 }*/
217                 Log::getInstance()->log("Video", Log::DEBUG, "Set deinterlacing to %s %d",option->options[option->userSetChoice],deinterlace);
218                 return true;
219         }
220         break;
221         };
222         return false;
223
224 }
225
226 bool VideoOMX::saveOptionstoServer()
227 {
228
229     switch (deinterlace) {
230         case 0:
231                 VDR::getInstance()->configSave("VideoOMX","SDDeinterlacing", "None");
232                 break;
233         /*case 1:
234                 VDR::getInstance()->configSave("VideoOMX","SDDeinterlacing", "LineDouble");
235                 break;*/
236         case 2:
237                 VDR::getInstance()->configSave("VideoOMX","SDDeinterlacing", "Advanced");
238                 break;
239         /*case 3:
240                 VDR::getInstance()->configSave("VideoOMX","SDDeinterlacing", "Crazy");
241                 break;*/
242         };
243
244     return true;
245 }
246
247 /*Option(UINT id, const char* displayText, const char* configSection, const char* configKey, UINT optionType,
248            UINT numChoices, UINT defaultChoice, UINT startInt,
249            const char * const * options, const char * const * optionkeys = NULL, AbstractOption* handler=NULL);*/
250
251 bool VideoOMX::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane)
252 {
253     if (!Video::addOptionsToPanes(panenumber,options,pane)) return false;
254
255
256     Option* option;
257     if (panenumber == 2)
258     {
259         static const char* deinterlaceopts[]={"None",/*"LineDouble",*/"Advanced"/*,"Crazy"*/};
260         option = new Option(1,tr("SD Deinterlacing"), "VideoOMX","SDDeinterlacing",Option::TYPE_TEXT,/*4,2*/2,1,0,deinterlaceopts,NULL,false,this);
261         options->push_back(option);
262         pane->addOptionLine(option);
263     }
264
265     return true;
266 }
267
268
269
270 int VideoOMX::setTVsize(UCHAR ttvsize)
271 {
272 /*  tvsize = ttvsize;
273
274   // Override the aspect ratio usage, temporarily use to set the video chip mode
275   if (!setAspectRatio(tvsize))       { shutdown(); return 0; }
276   close(fdVideo);
277   if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
278   if (!setSource())                  { shutdown(); return 0; }
279   if (!attachFramebuffer())          { shutdown(); return 0; }
280
281   // Reopening the fd causes the scart aspect line to go back to 4:3
282   // Set this again to the same as the tv screen size
283   if (!setAspectRatio(tvsize))       { shutdown(); return 0; }
284
285   // mode == LETTERBOX is invalid if the TV is widescreen
286   if (tvsize == ASPECT16X9) setMode(NORMAL);
287 */
288   return 1;
289 }
290
291 int VideoOMX::setDefaultAspect()
292 {
293   return setAspectRatio(tvsize);
294 }
295
296
297
298 int VideoOMX::setFormat(UCHAR tformat)
299 {
300   if (!initted) return 0;
301   if ((tformat != PAL) && (tformat != NTSC)) return 0;
302   format = PAL;
303   tvsystem = tformat;
304
305   if (format == PAL)
306   {
307     screenWidth = 720;
308     screenHeight = 576;
309   }
310
311 //  selectVideoMode(0);
312
313   return 1;
314 }
315
316 //void VideoOMX::selectVideoMode(int interlaced)
317 //{
318 //      if (/*hdmi*/ true) {
319 //              TV_SUPPORTED_MODE_T all_supp_modes[TV_MAX_SUPPORTED_MODES];
320 //              HDMI_RES_GROUP_T pref_group;
321 //              TV_SUPPORTED_MODE_T  *mymode=NULL;
322 //              TV_SUPPORTED_MODE_T  *mymode_second_best=NULL;
323 //              bool got_optimum=false;
324 //              uint32_t pref_mode;
325 //              int all_my_modes=vc_tv_hdmi_get_supported_modes(HDMI_RES_GROUP_CEA,
326 //                              all_supp_modes,TV_MAX_SUPPORTED_MODES,
327 //                              &pref_group,&pref_mode);
328 //              int target_fps=50;
329 //              if (format==PAL)target_fps=50;
330 //              else if (format==NTSC) target_fps=60;
331 //              if (all_my_modes<=0) {
332 //                       Log::getInstance()->log("Video", Log::NOTICE, "No CEA modes found abort");
333 //                      return;
334 //              }
335 //
336 //              //Now first determine native resolution
337 //              int native_width=1920;
338 //              int native_height=1080;
339 //              for (int i=0;i<all_my_modes;i++) {
340 //                      if (all_supp_modes[i].native) {
341 //                              mymode=all_supp_modes+i;
342 //                              Log::getInstance()->log("Video", Log::NOTICE, "Found native mode %dx%d %d Hz i: %d",
343 //                                              mymode->width,mymode->height,mymode->frame_rate,mymode->scan_mode);
344 //                      }
345 //
346 //              }
347 //              //Now find the mode which matches best
348 //              for (int i=0;i<all_my_modes;i++) {
349 //                      TV_SUPPORTED_MODE_T  *curmode=all_supp_modes+i;
350 //                      if (curmode->width==native_width &&
351 //                              curmode->height==native_height &&
352 //                               curmode->frame_rate==target_fps) {
353 //                                if(curmode->scan_mode==interlaced) {
354 //                                        got_optimum=true;
355 //                                        mymode=curmode;
356 //                                        Log::getInstance()->log("Video", Log::NOTICE, "Found optimum mode %dx%d %d Hz i: %d",
357 //                                                                                      mymode->width,mymode->height,mymode->frame_rate,mymode->scan_mode);
358 //                                } else {
359 //                                        mymode_second_best=curmode;
360 //                                        Log::getInstance()->log("Video", Log::NOTICE, "Found close to optimum mode %dx%d %d Hz i: %d",
361 //                                                                                              mymode_second_best->width,mymode_second_best->height,
362 //                                                                                              mymode_second_best->frame_rate,mymode_second_best->scan_mode);
363 //                              }
364 //
365 //                      }
366 //              }
367 //              if (mymode) {
368 //                      Log::getInstance()->log("Video", Log::NOTICE, "Switch to optimum mode");
369 //                      vc_tv_hdmi_power_on_explicit(HDMI_MODE_HDMI,HDMI_RES_GROUP_CEA,mymode->code);
370 //              } else if (mymode_second_best) {
371 //                      Log::getInstance()->log("Video", Log::NOTICE, "Switch to close to optimum mode");
372 //                      vc_tv_hdmi_power_on_explicit(HDMI_MODE_HDMI,HDMI_RES_GROUP_CEA,mymode_second_best->code);
373 //              } else {
374 //                      Log::getInstance()->log("Video", Log::NOTICE, "Switch to prefered mode");
375 //                      vc_tv_hdmi_power_on_best(1920,1080,target_fps,interlaced?HDMI_INTERLACED:HDMI_NONINTERLACED,
376 //                                      (EDID_MODE_MATCH_FLAG_T)(HDMI_MODE_MATCH_FRAMERATE|HDMI_MODE_MATCH_RESOLUTION|HDMI_MODE_MATCH_SCANMODE));
377 //              }
378 //
379 //      }
380 //
381 //
382 //
383 //}
384
385
386 int VideoOMX::setConnection(UCHAR tconnection)
387 {
388   if (!initted) return 0;
389   if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;
390   connection = tconnection;
391
392 //  if (ioctl(fdVideo, AV_SET_VID_OUTPUT, connection) != 0) return 0;
393   return 1;
394 }
395
396 int VideoOMX::setAspectRatio(UCHAR taspectRatio)
397 {
398   if (!initted) return 0;
399   if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
400   aspectRatio = taspectRatio;
401
402   Log::getInstance()->log("Video", Log::DEBUG, "Setting aspect to %i", aspectRatio);
403
404 //  if (ioctl(fdVideo, AV_SET_VID_RATIO, aspectRatio) != 0) return 0;
405   return 1;
406 }
407
408 int VideoOMX::setMode(UCHAR tmode)
409 {
410   if (!initted) return 0;
411   mode=tmode;
412   updateMode();
413   return 1;
414 }
415
416
417 void VideoOMX::updateMode()
418 {
419         clock_mutex.Lock();
420         if (omx_running) {
421                 OMX_ERRORTYPE error;
422                 OMX_CONFIG_DISPLAYREGIONTYPE dispconf;
423                 memset(&dispconf, 0, sizeof(dispconf));
424                 dispconf.nSize = sizeof(dispconf);
425                 dispconf.nVersion.nVersion = OMX_VERSION;
426                 dispconf.nPortIndex = omx_rend_input_port;
427                 dispconf.layer = 1;
428                 dispconf.set = OMX_DISPLAY_SET_LAYER;
429                 error = OMX_SetParameter(omx_vid_rend, OMX_IndexConfigDisplayRegion,
430                                 &dispconf);
431                 if (error != OMX_ErrorNone) {
432                         Log::getInstance()->log("Video", Log::DEBUG,
433                                         "Set OMX_IndexConfigDisplayRegion1 failed %x", error);
434                         clock_mutex.Unlock();
435                         return;
436                 }
437                 dispconf.set = OMX_DISPLAY_SET_FULLSCREEN;
438                 if (mode != QUARTER && mode != EIGHTH) {
439                         //Set Fullscreen
440                         dispconf.fullscreen = OMX_TRUE;
441                 } else {
442                         dispconf.fullscreen = OMX_FALSE;
443                 }
444                 error = OMX_SetParameter(omx_vid_rend, OMX_IndexConfigDisplayRegion,
445                                 &dispconf);
446                 if (error != OMX_ErrorNone) {
447                         Log::getInstance()->log("Video", Log::DEBUG,
448                                         "Set OMX_IndexConfigDisplayRegion2 failed %x", error);
449                         clock_mutex.Unlock();
450                         return;
451                 }
452
453                 dispconf.set = OMX_DISPLAY_SET_MODE;
454                 if (mode != QUARTER && mode != EIGHTH) {
455                         dispconf.mode = (mode == NORMAL) ? OMX_DISPLAY_MODE_FILL
456                                         : OMX_DISPLAY_MODE_LETTERBOX;
457                 } else {
458                         dispconf.mode = OMX_DISPLAY_MODE_LETTERBOX;
459                 }
460                 error = OMX_SetParameter(omx_vid_rend, OMX_IndexConfigDisplayRegion,
461                                 &dispconf);
462                 if (error != OMX_ErrorNone) {
463                         Log::getInstance()->log("Video", Log::DEBUG,
464                                         "Set OMX_IndexConfigDisplayRegion3 failed %x", error);
465                         clock_mutex.Unlock();
466                         return;
467                 }
468
469                 if (mode == QUARTER || mode == EIGHTH) {
470                         unsigned int display_width, display_height;
471                         display_width = display_height = 0;
472                         if (graphics_get_display_size(0, &display_width, &display_height)
473                                         < 0) {
474                                 Log::getInstance()->log("OSD", Log::WARN,
475                                                 "Getting display size failed! (BCM API) ");
476                                 clock_mutex.Unlock();
477                                 return;
478                         }
479                         //UnSetFullscreen with window
480                         dispconf.set = OMX_DISPLAY_SET_DEST_RECT;
481                         dispconf.dest_rect.x_offset
482                                         = (int) (xpos * ((float) display_width));
483                         dispconf.dest_rect.y_offset = (int) (ypos
484                                         * ((float) display_height));
485                         if (mode == QUARTER) {
486                                 dispconf.dest_rect.width = display_width >> 1;
487                                 dispconf.dest_rect.height = display_height >> 1;
488                         } else if (mode == EIGHTH) {
489                                 dispconf.dest_rect.width = display_width >> 2;
490                                 dispconf.dest_rect.height = display_height >> 2;
491                         }
492                         error = OMX_SetParameter(omx_vid_rend,
493                                         OMX_IndexConfigDisplayRegion, &dispconf);
494                         if (error != OMX_ErrorNone) {
495                                 Log::getInstance()->log("Video", Log::DEBUG,
496                                                 "Set OMX_IndexConfigDisplayRegion failed %x", error);
497                                 clock_mutex.Unlock();
498                                 return;
499                         }
500                 }
501
502         }
503         clock_mutex.Unlock();
504 }
505
506 int VideoOMX::signalOff()
507 {
508 //  if (ioctl(fdVideo, AV_SET_VID_DENC, 0) != 0) return 0;
509   return 1;
510 }
511
512 int VideoOMX::signalOn()
513 {
514 //  if (ioctl(fdVideo, AV_SET_VID_DENC, 1) != 0) return 0;
515   return 1;
516 }
517
518 int VideoOMX::setSource()
519 {
520   if (!initted) return 0;
521
522   // What does this do...
523 //  if (ioctl(fdVideo, AV_SET_VID_SRC, 1) != 0) return 0;
524   return 1;
525 }
526
527 int VideoOMX::setPosition(int x, int y) {
528         if (!initted)
529                 return 0;
530         xpos = ((float) x*2.f) / ((float) screenWidth);
531         ypos = ((float) y*2.f) / ((float) screenHeight);
532
533         updateMode();
534         return 1;
535 }
536
537 int VideoOMX::sync()
538 {
539   if (!initted) return 0;
540
541 //  if (ioctl(fdVideo, AV_SET_VID_SYNC, 2) != 0) return 0;
542   return 1;
543 }
544
545
546 int VideoOMX::play() {
547         if (!initted)
548                 return 0;
549         iframemode = false;
550         Log::getInstance()->log("Video", Log::DEBUG, "enter play");
551
552         if (AllocateCodecsOMX()) {
553                 return 1;
554                 // Otherwise fall back to libav
555         } else {
556                 if (h264) {
557                         omx_h264 = false;
558                         Log::getInstance()->log("Video", Log::NOTICE,
559                                         "Allocate Codecs OMX failed assume h264 unsupported");
560                 } else {
561                         omx_mpeg2 = false;
562                         Log::getInstance()->log("Video", Log::NOTICE,
563                                         "Allocate Codecs OMX failed assume mpeg2 unsupported");
564                 }
565         }
566
567         return 0;
568
569 }
570
571
572 int VideoOMX::initClock()
573 {
574         OMX_ERRORTYPE error;
575         clock_mutex.Lock();
576         if (clock_references==0)
577         {
578
579                 static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
580                 omx_events.clear();
581
582                 error=OMX_GetHandle(&omx_clock,VPE_OMX_CLOCK,NULL,&callbacks);
583
584                 if (error!=OMX_ErrorNone) {
585                         Log::getInstance()->log("Video", Log::DEBUG, "Init OMX clock failed %x", error);
586                         clock_mutex.Unlock();
587                         DeAllocateCodecsOMX();
588                         return 0;
589                 }
590
591                 /* TODO Clock config to separate method */
592                 OMX_PORT_PARAM_TYPE p_param;
593                 memset(&p_param,0,sizeof(p_param));
594                 p_param.nSize=sizeof(p_param);
595                 p_param.nVersion.nVersion=OMX_VERSION;
596                 error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param);
597                 if (error!=OMX_ErrorNone) {
598                         Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error);
599                         clock_mutex.Unlock();
600                         DeAllocateCodecsOMX();
601                         return 0;
602                 }
603                 omx_clock_output_port=p_param.nStartPortNumber;
604
605                 for (unsigned int i=0;i<p_param.nPorts;i++) {
606                         if (!DisablePort(omx_clock,p_param.nStartPortNumber+i,true) ) {
607                                 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX clock failed %d",i);
608                                 clock_mutex.Unlock();
609                                 DeAllocateCodecsOMX();
610                                 return 0;
611                         }
612                 }
613
614
615
616
617         }
618         Log::getInstance()->log("Video", Log::DEBUG, "init omx clock %x %x",this,omx_clock);
619         clock_references++;
620         clock_mutex.Unlock();
621         return 1;
622 }
623
624 int VideoOMX::getClockAudioandInit(OMX_HANDLETYPE *p_omx_clock,OMX_U32 *p_omx_clock_output_port)
625 {
626         OMX_ERRORTYPE error;
627         *p_omx_clock=NULL;
628         *p_omx_clock_output_port=0;
629
630         if (!initClock()) {
631                 return 0;
632         }
633         clock_mutex.Lock();
634
635         OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refclock;
636         memset(&refclock,0,sizeof(refclock));
637         refclock.nSize=sizeof(refclock);
638         refclock.nVersion.nVersion=OMX_VERSION;
639
640         refclock.eClock=OMX_TIME_RefClockAudio;
641
642         //refclock.eClock=OMX_TIME_RefClockVideo;
643         error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeActiveRefClock,&refclock);
644         if (error!=OMX_ErrorNone){
645                 Log::getInstance()->log("Video", Log::DEBUG, "Clock OMX_IndexConfigTimeActiveRefClock failed %x", error);
646                 clock_mutex.Unlock();
647                 DeAllocateCodecsOMX();
648                 return 0;
649         }
650
651         OMX_PORT_PARAM_TYPE p_param;
652         memset(&p_param,0,sizeof(p_param));
653         p_param.nSize=sizeof(p_param);
654         p_param.nVersion.nVersion=OMX_VERSION;
655         error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param);
656         if (error!=OMX_ErrorNone){
657                 Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error);
658                 clock_mutex.Unlock();
659                 DeAllocateCodecsOMX();
660                 return 0;
661         }
662
663         OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
664         memset(&clock_conf,0,sizeof(clock_conf));
665         clock_conf.nSize=sizeof(clock_conf);
666         clock_conf.nVersion.nVersion=OMX_VERSION;
667         clock_conf.eState=OMX_TIME_ClockStateWaitingForStartTime;
668         clock_conf.nStartTime=0;
669         clock_conf.nOffset=0;
670         if (clock_references==1) clock_conf.nWaitMask=OMX_CLOCKPORT1;
671         else clock_conf.nWaitMask=OMX_CLOCKPORT0|OMX_CLOCKPORT1;
672         error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
673         if (error!=OMX_ErrorNone) {
674                 Log::getInstance()->log("Video", Log::DEBUG, "AuI Clock IndexConfigTimeClockState failed %x", error);
675         }
676
677
678         *p_omx_clock_output_port=p_param.nStartPortNumber+1;
679         *p_omx_clock=omx_clock;
680         clock_mutex.Unlock();
681         return 1;
682 }
683
684 int VideoOMX::getClockVideoandInit()
685 {
686         OMX_ERRORTYPE error;
687
688         if (!initClock()) {
689                 return 0;
690         }
691         clock_mutex.Lock();
692
693         if (clock_references==1) { // only if no audio is attached to this clock!
694                 OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refclock;
695                 memset(&refclock,0,sizeof(refclock));
696                 refclock.nSize=sizeof(refclock);
697                 refclock.nVersion.nVersion=OMX_VERSION;
698
699                 //refclock.eClock=OMX_TIME_RefClockAudio;
700
701                 refclock.eClock=OMX_TIME_RefClockVideo;
702                 error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeActiveRefClock,&refclock);
703                 if (error!=OMX_ErrorNone) {
704                         Log::getInstance()->log("Video", Log::DEBUG, "Clock OMX_IndexConfigTimeActiveRefClock failed %x", error);
705                         clock_mutex.Unlock();
706                         DeAllocateCodecsOMX();
707                         return 0;
708                 }
709         }
710
711         OMX_PORT_PARAM_TYPE p_param;
712         memset(&p_param,0,sizeof(p_param));
713         p_param.nSize=sizeof(p_param);
714         p_param.nVersion.nVersion=OMX_VERSION;
715         error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param);
716         if (error!=OMX_ErrorNone){
717                 Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error);
718                 clock_mutex.Unlock();
719                 DeAllocateCodecsOMX();
720                 return 0;
721         }
722
723
724         OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
725         memset(&clock_conf,0,sizeof(clock_conf));
726         clock_conf.nSize=sizeof(clock_conf);
727         clock_conf.nVersion.nVersion=OMX_VERSION;
728         clock_conf.eState=OMX_TIME_ClockStateWaitingForStartTime;
729         clock_conf.nStartTime=0;
730         clock_conf.nOffset=0;
731         if (clock_references==1) clock_conf.nWaitMask=OMX_CLOCKPORT0;
732         else clock_conf.nWaitMask=OMX_CLOCKPORT0|OMX_CLOCKPORT1;
733         error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
734         if (error!=OMX_ErrorNone) {
735                 Log::getInstance()->log("Video", Log::DEBUG, "VuI Clock IndexConfigTimeClockState failed %x", error);
736         }
737
738         omx_clock_output_port=p_param.nStartPortNumber;
739         clock_mutex.Unlock();
740
741         return 1;
742 }
743
744 void VideoOMX::clockUnpause()
745 {
746         OMX_ERRORTYPE error;
747         clock_mutex.Lock();
748         if (clock_references>0) {
749                 OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
750                 memset(&clock_conf,0,sizeof(clock_conf));
751                 clock_conf.nSize=sizeof(clock_conf);
752                 clock_conf.nVersion.nVersion=OMX_VERSION;
753                 clock_conf.eState=OMX_TIME_ClockStateRunning;
754                 clock_conf.nStartTime=0;
755                 clock_conf.nOffset=0;
756                 clock_conf.nWaitMask=OMX_CLOCKPORT1;
757                 error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
758                 if (error!=OMX_ErrorNone) {
759                         Log::getInstance()->log("Video", Log::DEBUG, "ClockUnpause IndexConfigTimeClockState failed %x", error);
760                 }
761         }
762         clock_mutex.Unlock();
763 }
764
765
766 void VideoOMX::clockPause()
767 {
768         OMX_ERRORTYPE error;
769         clock_mutex.Lock();
770         if (clock_references>0) {
771                 OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
772                 memset(&clock_conf,0,sizeof(clock_conf));
773                 clock_conf.nSize=sizeof(clock_conf);
774                 clock_conf.nVersion.nVersion=OMX_VERSION;
775                 clock_conf.eState=OMX_TIME_ClockStateStopped;
776                 clock_conf.nStartTime=0;
777                 clock_conf.nOffset=0;
778                 clock_conf.nWaitMask=OMX_CLOCKPORT1;
779                 error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
780                 if (error!=OMX_ErrorNone) {
781                         Log::getInstance()->log("Video", Log::DEBUG, "ClockUnpause IndexConfigTimeClockState failed %x", error);
782                 }
783         }
784         clock_mutex.Unlock();
785 }
786
787
788
789 int VideoOMX::AllocateCodecsOMX()
790 {
791         OMX_ERRORTYPE error;
792         static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
793
794         Demuxer* demux=Demuxer::getInstance();
795
796         dodeint=false;
797         deint_first_frame=false;
798
799         Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX");
800         //Clock, move later to audio including events
801
802         if (deinterlace!=0 && demux->getHorizontalSize()<=720) { //only deinterlace SD material
803                 dodeint=true;
804                 deint_first_frame=true;
805
806                 Log::getInstance()->log("Video", Log::NOTICE, "Deinterlacing activated %d",deinterlace);
807
808         }
809
810
811         if (!getClockVideoandInit()){
812                 return 0;// get the clock and init it if necessary
813         }
814
815
816         if (!idleClock()) {
817                 Log::getInstance()->log("Video", Log::DEBUG, "idleClock failed");
818                 return 0;
819         }
820         /* TODO end */
821
822
823         clock_mutex.Lock();
824         if (h264) {
825                 error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_H264_DECODER,NULL,&callbacks);
826         } else {
827                 error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_MPEG2_DECODER,NULL,&callbacks);
828         }
829
830         if (error!=OMX_ErrorNone){
831                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video decoder failed %x", error);
832                 clock_mutex.Unlock();
833                 DeAllocateCodecsOMX();
834                 return 0;
835         }
836
837
838         Log::getInstance()->log("Video", Log::DEBUG, "Nmark3 ");
839         OMX_PORT_PARAM_TYPE p_param;
840         memset(&p_param,0,sizeof(p_param));
841         p_param.nSize=sizeof(p_param);
842         p_param.nVersion.nVersion=OMX_VERSION;
843         error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamVideoInit,&p_param);
844         if (error!=OMX_ErrorNone){
845                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX h264 decoder OMX_GetParameter failed %x", error);
846                 clock_mutex.Unlock();
847                 DeAllocateCodecsOMX();
848             return 0;
849         }
850         omx_codec_input_port=p_param.nStartPortNumber;
851         omx_codec_output_port=p_param.nStartPortNumber+1;
852
853         if (!DisablePort(omx_vid_dec,omx_codec_input_port) || !DisablePort(omx_vid_dec,omx_codec_output_port)) {
854                 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video decoder failed");
855                 clock_mutex.Unlock();
856                 DeAllocateCodecsOMX();
857                 return 0;
858         }
859
860         Log::getInstance()->log("Video", Log::DEBUG, "Nmark4 ");
861
862         OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE conceal;
863         memset(&conceal,0,sizeof(conceal));
864         conceal.nSize=sizeof(conceal);
865         conceal.nVersion.nVersion=OMX_VERSION;
866         conceal.bStartWithValidFrame=OMX_FALSE;
867
868         error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamBrcmVideoDecodeErrorConcealment,&conceal);
869         if (error!=OMX_ErrorNone){
870                 Log::getInstance()->log("Video", Log::DEBUG, "OMX_IndexParamBrcmVideoDecodeErrorConcealment failed %x", error);
871                 clock_mutex.Unlock();
872                 DeAllocateCodecsOMX();
873                 return 0;
874         }
875
876         if (dodeint) {
877                 error = OMX_GetHandle(&omx_vid_deint, VPE_OMX_VIDEO_DEINTERLACE, NULL,
878                                 &callbacks);
879                 if (error != OMX_ErrorNone) {
880                         Log::getInstance()->log("Video", Log::DEBUG,
881                                         "Init OMX video deinterlacer failed %x", error);
882                         clock_mutex.Unlock();
883                         DeAllocateCodecsOMX();
884                         return 0;
885                 }
886
887                 error = OMX_GetParameter(omx_vid_deint, OMX_IndexParamImageInit,
888                                 &p_param);
889                 if (error != OMX_ErrorNone) {
890                         Log::getInstance()->log("Video", Log::DEBUG,
891                                         "Init OMX video deinterlacer OMX_GetParameter failed %x",
892                                         error);
893                         clock_mutex.Unlock();
894                         DeAllocateCodecsOMX();
895                         return 0;
896                 }
897                 omx_deint_input_port = p_param.nStartPortNumber;
898                 omx_deint_output_port = p_param.nStartPortNumber + 1;
899
900                 if (!DisablePort(omx_vid_deint, omx_deint_input_port, true)
901                                 || !DisablePort(omx_vid_deint, omx_deint_output_port, true)) {
902                         Log::getInstance()->log("Video", Log::DEBUG,
903                                         "Disable Ports OMX video deint failed");
904                         clock_mutex.Unlock();
905                         DeAllocateCodecsOMX();
906                         return 0;
907                 }
908
909         }
910
911
912         error=OMX_GetHandle(&omx_vid_sched,VPE_OMX_VIDEO_SCHED,NULL,&callbacks);
913         if (error!=OMX_ErrorNone){
914                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler failed %x", error);
915                 clock_mutex.Unlock();
916                 DeAllocateCodecsOMX();
917                 return 0;
918         }
919
920
921
922         error=OMX_GetParameter(omx_vid_sched,OMX_IndexParamVideoInit,&p_param);
923         if (error!=OMX_ErrorNone){
924                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler OMX_GetParameter failed %x", error);
925                 clock_mutex.Unlock();
926                 DeAllocateCodecsOMX();
927                 return 0;
928         }
929         omx_shed_input_port=p_param.nStartPortNumber;
930         omx_shed_output_port=p_param.nStartPortNumber+1;
931
932
933         error=OMX_GetParameter(omx_vid_sched,OMX_IndexParamOtherInit,&p_param);
934         if (error!=OMX_ErrorNone){
935                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler OMX_GetParameter failed %x", error);
936                 clock_mutex.Unlock();
937                 DeAllocateCodecsOMX();
938                 return 0;
939         }
940         omx_shed_clock_port=p_param.nStartPortNumber;
941         Log::getInstance()->log("Video", Log::DEBUG, "scheduler ports %d %d %d ",omx_shed_input_port,omx_shed_output_port,omx_shed_clock_port);
942
943
944         if (!DisablePort(omx_vid_sched,omx_shed_input_port,true) || !DisablePort(omx_vid_sched,omx_shed_output_port,true)
945                         || !DisablePort(omx_vid_sched,omx_shed_clock_port,true)) {
946                 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video shed failed");
947                 clock_mutex.Unlock();
948                 DeAllocateCodecsOMX();
949                 return 0;
950         }
951
952
953         error=OMX_GetHandle(&omx_vid_rend,VPE_OMX_VIDEO_REND,NULL,&callbacks);
954         if (error!=OMX_ErrorNone){
955                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video rend failed %x", error);
956                 clock_mutex.Unlock();
957                 DeAllocateCodecsOMX();
958                 return 0;
959         }
960
961         error=OMX_GetParameter(omx_vid_rend,OMX_IndexParamVideoInit,&p_param);
962         if (error!=OMX_ErrorNone){
963                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video rend OMX_GetParameter failed %x", error);
964                 clock_mutex.Unlock();
965                 DeAllocateCodecsOMX();
966                 return 0;
967         }
968         omx_rend_input_port=p_param.nStartPortNumber;
969         //omx_rend_output_port=p_param.nStartPortNumber+1;
970
971
972         if (!DisablePort(omx_vid_rend,omx_rend_input_port,true) /*|| !DisablePort(omx_vid_rend,omx_rend_output_port)*/
973                                 ) {
974                 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video rend failed");
975                 clock_mutex.Unlock();
976                 DeAllocateCodecsOMX();
977                 return 0;
978         }
979
980         //Setuo chain
981
982
983
984         error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,omx_vid_sched,omx_shed_clock_port);
985         if (error!=OMX_ErrorNone){
986                 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);
987                 clock_mutex.Unlock();
988                 DeAllocateCodecsOMX();
989                 return 0;
990         }
991
992         if (!EnablePort(omx_clock,omx_clock_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_clock_port,false)
993                                         ) {
994                 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX clock shed failed");
995                 clock_mutex.Unlock();
996                 DeAllocateCodecsOMX();
997                 return 0;
998         }
999
1000
1001         Log::getInstance()->log("Video", Log::DEBUG, "mark2 ");
1002         if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) {
1003                 Log::getInstance()->log("Video", Log::DEBUG, "vid_sched idle ChangeComponentState");
1004                 clock_mutex.Unlock();
1005                 DeAllocateCodecsOMX();
1006                 return 0;
1007         }
1008
1009
1010
1011         Log::getInstance()->log("Video", Log::DEBUG, "mark1 ");
1012         if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_clock_port)) {
1013                 clock_mutex.Unlock();
1014                 DeAllocateCodecsOMX();
1015                 return 0;
1016         }
1017
1018
1019
1020
1021         Log::getInstance()->log("Video", Log::DEBUG, "mark1 special ");
1022         if ( !CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port)) {
1023                 clock_mutex.Unlock();
1024                 DeAllocateCodecsOMX();
1025                 return 0;
1026         }
1027
1028
1029
1030         Log::getInstance()->log("Video", Log::DEBUG, "mark1b ");
1031
1032
1033 /*      error=OMX_SendCommand(omx_vid_dec,OMX_CommandStateSet,OMX_StateIdle,0);
1034         if (error!=OMX_ErrorNone){
1035                 Log::getInstance()->log("Video", Log::DEBUG, "vid_dec Send Command to OMX State Idle %x", error);
1036                 return 0;
1037         }*/
1038
1039         OMX_VIDEO_PARAM_PORTFORMATTYPE ft_type;
1040         memset(&ft_type,0,sizeof(ft_type));
1041         ft_type.nSize=sizeof(ft_type);
1042         ft_type.nVersion.nVersion=OMX_VERSION;
1043
1044         ft_type.nPortIndex=omx_codec_input_port;
1045         if (h264) {
1046                 ft_type.eCompressionFormat=OMX_VIDEO_CodingAVC;
1047         } else {
1048                 ft_type.eCompressionFormat=OMX_VIDEO_CodingMPEG2;
1049         }
1050
1051
1052
1053     ft_type.xFramerate=0;//25*(1<<16);//demux->getFrameRate()*(1<<16);
1054     Log::getInstance()->log("Video", Log::DEBUG, "Framerate: %d",demux->getFrameRate());
1055         error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamVideoPortFormat,&ft_type);
1056         if (error!=OMX_ErrorNone){
1057                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexParamVideoPortFormat failed %x", error);
1058                 clock_mutex.Unlock();
1059                 DeAllocateCodecsOMX();
1060                 return 0;
1061         }
1062
1063
1064         if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) {
1065                 Log::getInstance()->log("Video", Log::DEBUG, "vid_dec ChangeComponentState");
1066                 clock_mutex.Unlock();
1067                 DeAllocateCodecsOMX();
1068                 return 0;
1069         }
1070
1071
1072         if (!PrepareInputBufsOMX()) {
1073                 clock_mutex.Unlock();
1074                 DeAllocateCodecsOMX();
1075                 return 0;
1076         }
1077
1078         if (!dodeint) {
1079                 error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,omx_vid_sched,omx_shed_input_port);
1080                 if (error!=OMX_ErrorNone){
1081                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel dec to sched failed %x", error);
1082                         clock_mutex.Unlock();
1083                         DeAllocateCodecsOMX();
1084                         return 0;
1085                 }
1086
1087
1088
1089                 if (!EnablePort(omx_vid_dec,omx_codec_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_input_port,false)
1090                 ) {
1091                         Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX codec shed failed");
1092                         clock_mutex.Unlock();
1093                         DeAllocateCodecsOMX();
1094                         return 0;
1095                 }
1096
1097                 if ( !CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_output_port) || !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_input_port)) {
1098                         clock_mutex.Unlock();
1099                         DeAllocateCodecsOMX();
1100                         return 0;
1101                 }
1102
1103         } else {
1104
1105                 error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,omx_vid_deint,omx_deint_input_port);
1106                 if (error!=OMX_ErrorNone){
1107                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel dec to deint failed %x", error);
1108                         clock_mutex.Unlock();
1109                         DeAllocateCodecsOMX();
1110                         return 0;
1111                 }
1112
1113
1114
1115                 if (!EnablePort(omx_vid_dec,omx_codec_output_port,false) || !EnablePort(omx_vid_deint,omx_deint_input_port,false)
1116                 ) {
1117                         Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX codec deint failed");
1118                         clock_mutex.Unlock();
1119                         DeAllocateCodecsOMX();
1120                         return 0;
1121                 }
1122
1123                 if ( !CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_output_port) || !CommandFinished(omx_vid_deint,OMX_CommandPortEnable,omx_deint_input_port)) {
1124                         clock_mutex.Unlock();
1125                         DeAllocateCodecsOMX();
1126                         return 0;
1127                 }
1128
1129                 if (!ChangeComponentState(omx_vid_deint,OMX_StateIdle)) {
1130                         Log::getInstance()->log("Video", Log::DEBUG, "vid_deint ChangeComponentState");
1131                         clock_mutex.Unlock();
1132                         DeAllocateCodecsOMX();
1133                         return 0;
1134                 }
1135
1136                 OMX_CONFIG_IMAGEFILTERPARAMSTYPE imagefilter;
1137                 memset(&imagefilter,0,sizeof(imagefilter));
1138                 imagefilter.nSize=sizeof(imagefilter);
1139                 imagefilter.nVersion.nVersion=OMX_VERSION;
1140
1141                 imagefilter.nPortIndex=omx_deint_output_port;
1142                 imagefilter.nNumParams=1;
1143                 imagefilter.nParams[0]=3;//???
1144                 switch (deinterlace) {
1145                 case 1:
1146                         imagefilter.eImageFilter=OMX_ImageFilterDeInterlaceLineDouble; break;
1147                 case 2:
1148                         imagefilter.eImageFilter=OMX_ImageFilterDeInterlaceAdvanced; break;
1149                 case 3:
1150                         imagefilter.eImageFilter=OMX_ImageFilterFilm; break;
1151                 }
1152
1153
1154                 error=OMX_SetConfig(omx_vid_deint,OMX_IndexConfigCommonImageFilterParameters,&imagefilter);
1155                 if (error!=OMX_ErrorNone){
1156                         Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigCommonImageFilterParameters failed %x", error);
1157                         clock_mutex.Unlock();
1158                         DeAllocateCodecsOMX();
1159                         return 0;
1160                 }
1161
1162
1163                 error=OMX_SetupTunnel(omx_vid_deint,omx_deint_output_port,omx_vid_sched,omx_shed_input_port);
1164                 if (error!=OMX_ErrorNone){
1165                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel deint to sched failed %x", error);
1166                         clock_mutex.Unlock();
1167                         DeAllocateCodecsOMX();
1168                         return 0;
1169                 }
1170
1171                 if (!EnablePort(omx_vid_deint,omx_deint_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_input_port,false)
1172                 ) {
1173                         Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX deint shed failed");
1174                         clock_mutex.Unlock();
1175                         DeAllocateCodecsOMX();
1176                         return 0;
1177                 }
1178
1179                 if ( !CommandFinished(omx_vid_deint,OMX_CommandPortEnable,omx_deint_output_port) || !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_input_port)) {
1180                         clock_mutex.Unlock();
1181                         DeAllocateCodecsOMX();
1182                         return 0;
1183                 }
1184
1185         }
1186
1187         if (!ChangeComponentState(omx_vid_dec,OMX_StateExecuting)) {
1188                 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_dec ChangeComponentState Execute");
1189                 clock_mutex.Unlock();
1190                 DeAllocateCodecsOMX();
1191                 return 0;
1192         }
1193
1194         error=OMX_SetupTunnel(omx_vid_sched,omx_shed_output_port,omx_vid_rend,omx_rend_input_port);
1195         if (error!=OMX_ErrorNone){
1196                 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel  sched to rend failed %x", error);
1197                 clock_mutex.Unlock();
1198                 DeAllocateCodecsOMX();
1199                 return 0;
1200         }
1201
1202         if (!EnablePort(omx_vid_sched,omx_shed_output_port,false) || !EnablePort(omx_vid_rend,omx_rend_input_port,false)
1203                                                         ) {
1204                 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX  shed rend failed");
1205                 clock_mutex.Unlock();
1206                 DeAllocateCodecsOMX();
1207                 return 0;
1208         }
1209
1210         if (!CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_output_port)
1211                                         || !CommandFinished(omx_vid_rend,OMX_CommandPortEnable,omx_rend_input_port)) {
1212                 clock_mutex.Unlock();
1213                 DeAllocateCodecsOMX();
1214                 return 0;
1215         }
1216
1217         if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) {
1218                 Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState");
1219                 clock_mutex.Unlock();
1220                 DeAllocateCodecsOMX();
1221                 return 0;
1222         }
1223
1224         if (dodeint) {
1225                 if (!ChangeComponentState(omx_vid_deint,OMX_StateExecuting)) {
1226                         Log::getInstance()->log("Video", Log::DEBUG, "vid_vid_deint ChangeComponentState");
1227                         clock_mutex.Unlock();
1228                         DeAllocateCodecsOMX();
1229                         return 0;
1230                 }
1231                 DisablePort(omx_vid_deint,omx_deint_output_port,false);
1232                 DisablePort(omx_vid_deint,omx_deint_input_port,false);
1233         }
1234
1235         if (!ChangeComponentState(omx_vid_sched,OMX_StateExecuting)) {
1236                 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_sched ChangeComponentState Execute");
1237                 clock_mutex.Unlock();
1238                 DeAllocateCodecsOMX();
1239                 return 0;
1240         }
1241
1242         if (!ChangeComponentState(omx_vid_rend,OMX_StateExecuting)) {
1243                 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_rend ChangeComponentState Execute");
1244                 clock_mutex.Unlock();
1245                 DeAllocateCodecsOMX();
1246                 return 0;
1247         }
1248
1249         //raspbi specifif
1250         /*OMX_CONFIG_DISPLAYREGIONTYPE dispconf;
1251         memset(&dispconf,0,sizeof(dispconf));
1252         dispconf.nSize=sizeof(dispconf);
1253         dispconf.nVersion.nVersion=OMX_VERSION;
1254
1255         dispconf.nPortIndex=omx_rend_input_port;
1256
1257         dispconf.set=OMX_DISPLAY_SET_LAYER ;
1258         dispconf.layer=1;
1259         error=OMX_SetConfig(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
1260         if (error!=OMX_ErrorNone){
1261                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
1262                 clock_mutex.Unlock();
1263                 DeAllocateCodecsOMX();
1264                 return 0;
1265         }*/
1266
1267 /*      dispconf.set=OMX_DISPLAY_SET_FULLSCREEN ;
1268         dispconf.fullscreen=OMX_FALSE;
1269         error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
1270         if (error!=OMX_ErrorNone){
1271                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
1272                 clock_mutex.Unlock();
1273                 DeAllocateCodecsOMX();
1274                 return 0;
1275         }
1276
1277         dispconf.set=OMX_DISPLAY_SET_DEST_RECT;
1278         dispconf.dest_rect.x_offset=100;
1279         dispconf.dest_rect.y_offset=100;
1280         dispconf.dest_rect.width=640;
1281         dispconf.dest_rect.height=480;
1282         error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
1283         if (error!=OMX_ErrorNone){
1284                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
1285                 clock_mutex.Unlock();
1286                 DeAllocateCodecsOMX();
1287                 return 0;
1288         }*/
1289
1290
1291         playbacktimeoffset=-GetCurrentSystemTime();
1292         paused=false;
1293         iframemode=false;
1294         omx_running=true;
1295         clock_mutex.Unlock();
1296         updateMode();
1297         threadStart();
1298
1299         setClockExecutingandRunning();
1300
1301
1302
1303
1304
1305         return 1;
1306 }
1307
1308 int VideoOMX::idleClock()
1309 {
1310         OMX_ERRORTYPE error;
1311         OMX_STATETYPE temp_state;
1312         clock_mutex.Lock();
1313         OMX_GetState(omx_clock,&temp_state);
1314
1315         if (temp_state!=OMX_StateIdle) {
1316                 if (!ChangeComponentState(omx_clock,OMX_StateIdle)) {
1317                         Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Idle failed");
1318                         clock_mutex.Unlock();
1319                         return 0;
1320                 }
1321         }
1322         clock_mutex.Unlock();
1323         return 1;
1324 }
1325
1326 int VideoOMX::setClockExecutingandRunning()
1327 {
1328         OMX_ERRORTYPE error;
1329         OMX_STATETYPE temp_state;
1330         clock_mutex.Lock();
1331         OMX_GetState(omx_clock,&temp_state);
1332
1333         if (temp_state!=OMX_StateExecuting) {
1334                 if (!ChangeComponentState(omx_clock,OMX_StateExecuting)) {
1335                         Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Execute failed");
1336                         clock_mutex.Unlock();
1337                         DeAllocateCodecsOMX();
1338                         return 0;
1339                 }
1340         }
1341
1342         OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
1343         memset(&clock_conf,0,sizeof(clock_conf));
1344         clock_conf.nSize=sizeof(clock_conf);
1345         clock_conf.nVersion.nVersion=OMX_VERSION;
1346         clock_conf.eState=OMX_TIME_ClockStateRunning;
1347         error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
1348         if (error!=OMX_ErrorNone) {
1349                 Log::getInstance()->log("Video", Log::DEBUG, "Clock IndexConfigTimeClockState failed %x", error);
1350                 clock_mutex.Unlock();
1351                 DeAllocateCodecsOMX();
1352                 return 0;
1353         }
1354         clock_mutex.Unlock();
1355         return 1;
1356
1357 }
1358
1359
1360 int VideoOMX::ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type) //needs to be called with locked mutex
1361 {
1362         OMX_ERRORTYPE error;
1363         error=OMX_SendCommand(handle,OMX_CommandStateSet,type,0);
1364         if (error!=OMX_ErrorNone){
1365                 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to OMX State %x %x",handle,type, error);
1366                 return 0;
1367         }
1368
1369         if (!CommandFinished(handle,OMX_CommandStateSet,type)) {
1370                 return 0;
1371         }
1372
1373         return 1;
1374 }
1375
1376
1377 int VideoOMX::EnablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait) //needs to be called with locked mutex
1378 {
1379         OMX_ERRORTYPE error;
1380         error=OMX_SendCommand(handle,OMX_CommandPortEnable,port,0);
1381         if (error!=OMX_ErrorNone){
1382                 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to enable port %x %x",handle,port, error);
1383                 return 0;
1384         }
1385
1386         if (!wait) return 1;
1387         if (!CommandFinished(handle,OMX_CommandPortEnable,port)) {
1388                 return 0;
1389         }
1390
1391         return 1;
1392 }
1393
1394
1395 int VideoOMX::DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait) //needs to be called with locked mutex
1396 {
1397         OMX_ERRORTYPE error;
1398         error=OMX_SendCommand(handle,OMX_CommandPortDisable,port,0);
1399         if (error!=OMX_ErrorNone){
1400                 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to disable port %x %x",handle,port, error);
1401                 return 0;
1402         }
1403
1404         if (!wait) return 1;
1405         if (!CommandFinished(handle,OMX_CommandPortDisable,port)) {
1406                 return 0;
1407         }
1408
1409
1410         return 1;
1411 }
1412
1413 int VideoOMX::WaitForEvent(OMX_HANDLETYPE handle,OMX_U32 event) //needs to be called with locked mutex
1414 {
1415         int i=0;
1416         while (i<1000) {
1417                 omx_event_mutex.Lock();
1418                 list<VPE_OMX_EVENT>::iterator itty=omx_events.begin();
1419                 while (itty!=omx_events.end()) {
1420
1421                         VPE_OMX_EVENT current=*itty;
1422                         if (current.handle==handle) { //this is ours
1423                                 if (current.event_type==OMX_EventError) {
1424                                         omx_events.erase(itty);
1425                                         omx_event_mutex.Unlock();
1426                                         Log::getInstance()->log("Video", Log::DEBUG, "WaitForEvent Finished on Error");
1427                                         return 0;
1428
1429                                 } else if (current.event_type==event) {
1430                                         omx_events.erase(itty);
1431                                         omx_event_mutex.Unlock();
1432                                         Log::getInstance()->log("Video", Log::DEBUG, "WaitForEvent Finished Completed");
1433                                         return 1;
1434                                 }
1435                         }
1436                         itty++;
1437
1438                 }
1439                 omx_event_mutex.Unlock();
1440                 MILLISLEEP(2);
1441                 i++;
1442
1443         }
1444         Log::getInstance()->log("Video", Log::DEBUG, "WaitForEvent waited too long %x %x",handle,event);
1445         return 0;
1446
1447 }
1448
1449
1450 int VideoOMX::CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2) //needs to be called with locked mutex
1451 {
1452         int i=0;
1453         while (i<1000) {
1454                 omx_event_mutex.Lock();
1455                 list<VPE_OMX_EVENT>::iterator itty=omx_events.begin();
1456                 while (itty!=omx_events.end()) {
1457
1458                         VPE_OMX_EVENT current=*itty;
1459                         if (current.handle==handle) { //this is ours
1460                                 if (current.event_type==OMX_EventError) {
1461                                         omx_events.erase(itty);
1462                                         omx_event_mutex.Unlock();
1463                                         Log::getInstance()->log("Video", Log::DEBUG, "Command Finished on Error");
1464                                         return 0;
1465
1466                                 } else if (current.event_type==OMX_EventCmdComplete && current.data1==command && current.data2==data2) {
1467                                         omx_events.erase(itty);
1468                                         omx_event_mutex.Unlock();
1469                                         //Log::getInstance()->log("Video", Log::DEBUG, "Command Finished Completed");
1470                                         return 1;
1471                                 }
1472                         }
1473                         itty++;
1474
1475                 }
1476                 omx_event_mutex.Unlock();
1477                 MILLISLEEP(2);
1478                 i++;
1479
1480         }
1481         Log::getInstance()->log("Video", Log::DEBUG, "CommandFinished waited too long %x %x %x",handle,command, data2);
1482         return 0;
1483
1484 }
1485
1486
1487
1488
1489
1490 int VideoOMX::PrepareInputBufsOMX() //needs to be called with locked mutex
1491 {
1492         OMX_ERRORTYPE error;
1493         OMX_PARAM_PORTDEFINITIONTYPE port_def_type;
1494         memset(&port_def_type,0,sizeof(port_def_type));
1495         port_def_type.nSize=sizeof(port_def_type);
1496         port_def_type.nVersion.nVersion=OMX_VERSION;
1497         port_def_type.nPortIndex=omx_codec_input_port;
1498
1499         error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type);
1500
1501         if (error!=OMX_ErrorNone){
1502                         Log::getInstance()->log("Video", Log::DEBUG, "Get OMX OMX_IndexParamPortDefinition failed %x", error);
1503         }
1504 /*      Log::getInstance()->log("Video", Log::DEBUG, "Port para %d %d %d %d %d %d %d", port_def_type.nBufferCountActual,
1505                         port_def_type.nBufferCountMin,port_def_type.nBufferSize,port_def_type.bEnabled,port_def_type.bPopulated,
1506                         port_def_type.bBuffersContiguous,port_def_type.nBufferAlignment);*/
1507
1508         port_def_type.nBufferCountActual=100;
1509         port_def_type.nBufferSize=max(port_def_type.nBufferSize,200000); // for transcoder important
1510
1511         error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type);
1512
1513         if (error!=OMX_ErrorNone){
1514                         Log::getInstance()->log("Video", Log::DEBUG, "Set OMX OMX_IndexParamPortDefinition failed %x", error);
1515         }
1516
1517
1518         error=OMX_SendCommand(omx_vid_dec,OMX_CommandPortEnable,omx_codec_input_port,0);
1519         if (error!=OMX_ErrorNone){
1520                 Log::getInstance()->log("Video", Log::DEBUG, "Prepare Input bufs Send Command to enable port %x", error);
1521                 return 0;
1522         }
1523
1524         input_bufs_omx_mutex.Lock();
1525         for (unsigned int i=0; i< port_def_type.nBufferCountActual;i++) {
1526
1527         //      unsigned char* new_buffer_data=(unsigned char*)malloc(port_def_type.nbufferSize);
1528                 OMX_BUFFERHEADERTYPE *buf_head=NULL;
1529         /*      error=OMX_Usebuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nbufferSize,new_buffer_data);
1530                 if (error!=OMX_ErrorNone){
1531                         Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_Usebuffer failed %x", error);
1532                         input_bufs_omx_mutex.Unlock();
1533                         return 0;
1534                 }*/
1535                 error=OMX_AllocateBuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nBufferSize);
1536                 if (error!=OMX_ErrorNone){
1537                         Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_AllocateBuffer failed %x", error);
1538                                 input_bufs_omx_mutex.Unlock();
1539                         return 0;
1540                 }
1541                 input_bufs_omx_all.push_back(buf_head);
1542                 input_bufs_omx_free.push_back(buf_head);
1543         }
1544         omx_first_frame=true;
1545
1546         firstsynched=false;
1547         cur_input_buf_omx=NULL;
1548         input_bufs_omx_mutex.Unlock();
1549
1550
1551         Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark3");
1552         if (!CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_input_port)) {
1553                 return 0;
1554         }
1555         Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark4");
1556
1557         return 1;
1558 }
1559
1560 int VideoOMX::DestroyInputBufsOMX() //need s to be called with locked mutex
1561 {
1562         OMX_ERRORTYPE error;
1563
1564         cur_input_buf_omx=NULL;
1565         input_bufs_omx_mutex.Lock();
1566         for (int i=0; i< input_bufs_omx_all.size();i++) {
1567         //      free(input_bufs_omx_all[i]->pBuffer);
1568         //      input_bufs_omx_all[i]->pBuffer=NULL;
1569                 error=OMX_FreeBuffer(omx_vid_dec,omx_codec_input_port,input_bufs_omx_all[i]);
1570                 if (error!=OMX_ErrorNone){
1571                         Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_FreeBuffer failed %x", error);
1572                         input_bufs_omx_mutex.Unlock();
1573                         return 0;
1574                 }
1575
1576         }
1577         input_bufs_omx_all.clear();
1578         input_bufs_omx_free.clear();
1579         input_bufs_omx_present.clear();
1580         input_time_present.clear();
1581         input_time_pts.clear();
1582         input_is_last.clear();
1583         input_bufs_omx_mutex.Unlock();
1584
1585 }
1586
1587
1588
1589
1590 int VideoOMX::DeAllocateCodecsOMX()
1591 {
1592         OMX_ERRORTYPE error;
1593         omx_running=false;
1594           Log::getInstance()->log("Video", Log::DEBUG, "enter deallocatecodecsomx");
1595         threadStop();
1596
1597
1598    if (cur_input_buf_omx) {
1599                 cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_EOS;
1600                 OMX_ERRORTYPE error=ProtOMXEmptyThisBuffer(omx_vid_dec,cur_input_buf_omx);
1601                 if (error!=OMX_ErrorNone) {
1602                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error);
1603                 }
1604
1605                 cur_input_buf_omx=NULL;//write out old data
1606         }
1607    clock_mutex.Lock();
1608         if (omx_vid_dec) {
1609                 // first stop the omx elements
1610                 if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) {
1611                         Log::getInstance()->log("Video", Log::DEBUG, "vid_dec ChangeComponentState");
1612
1613                 }
1614                 clock_mutex.Unlock();
1615
1616                 idleClock();
1617                 clock_mutex.Lock();
1618
1619                 if (dodeint) {
1620                         if (!ChangeComponentState(omx_vid_deint, OMX_StateIdle)) {
1621                                 Log::getInstance()->log("Video", Log::DEBUG,
1622                                                 "vid_deint ChangeComponentState");
1623
1624                         }
1625                 }
1626
1627
1628                 if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) {
1629                         Log::getInstance()->log("Video", Log::DEBUG, "vid_shed ChangeComponentState");
1630
1631                 }
1632
1633                 if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) {
1634                         Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState");
1635
1636                 }
1637
1638
1639
1640         // TODO proper deinit sequence
1641                 // first flush all buffers
1642
1643                 if (!dodeint) {
1644
1645                         error = OMX_SendCommand(omx_vid_dec, OMX_CommandFlush,
1646                                         omx_codec_output_port, NULL);
1647                         if (error != OMX_ErrorNone) {
1648                                 Log::getInstance()->log("Video", Log::DEBUG,
1649                                                 "OMX_Flush codec out failed %x", error);
1650
1651                         }
1652
1653                         error = OMX_SendCommand(omx_vid_sched, OMX_CommandFlush,
1654                                         omx_shed_input_port, NULL);
1655                         if (error != OMX_ErrorNone) {
1656                                 Log::getInstance()->log("Video", Log::DEBUG,
1657                                                 "OMX_Flush shed in failed %x", error);
1658
1659                         }
1660
1661                         if (!CommandFinished(omx_vid_dec, OMX_CommandFlush,
1662                                         omx_codec_output_port)) {
1663                                 Log::getInstance()->log("Video", Log::DEBUG,
1664                                                 "flush cmd codec  failed");
1665                         }
1666
1667                         if (!CommandFinished(omx_vid_sched, OMX_CommandFlush,
1668                                         omx_shed_input_port)) {
1669                                 Log::getInstance()->log("Video", Log::DEBUG,
1670                                                 "flush cmd  shed failed");
1671                         }
1672                 } else {
1673                         error = OMX_SendCommand(omx_vid_dec, OMX_CommandFlush,
1674                                         omx_codec_output_port, NULL);
1675                         if (error != OMX_ErrorNone) {
1676                                 Log::getInstance()->log("Video", Log::DEBUG,
1677                                                 "OMX_Flush codec out failed %x", error);
1678
1679                         }
1680
1681                         error = OMX_SendCommand(omx_vid_deint, OMX_CommandFlush,
1682                                         omx_deint_input_port, NULL);
1683                         if (error != OMX_ErrorNone) {
1684                                 Log::getInstance()->log("Video", Log::DEBUG,
1685                                                 "OMX_Flush deint in failed %x", error);
1686
1687                         }
1688
1689                         if (!CommandFinished(omx_vid_dec, OMX_CommandFlush,
1690                                         omx_codec_output_port)) {
1691                                 Log::getInstance()->log("Video", Log::DEBUG,
1692                                                 "flush cmd codec  failed");
1693                         }
1694
1695                         if (!CommandFinished(omx_vid_deint, OMX_CommandFlush,
1696                                         omx_deint_input_port)) {
1697                                 Log::getInstance()->log("Video", Log::DEBUG,
1698                                                 "flush cmd  deint failed");
1699                         }
1700
1701                         //m
1702                         error = OMX_SendCommand(omx_vid_deint, OMX_CommandFlush,
1703                                         omx_deint_output_port, NULL);
1704                         if (error != OMX_ErrorNone) {
1705                                 Log::getInstance()->log("Video", Log::DEBUG,
1706                                                 "OMX_Flush deint out failed %x", error);
1707
1708                         }
1709
1710                         error = OMX_SendCommand(omx_vid_sched, OMX_CommandFlush,
1711                                         omx_shed_input_port, NULL);
1712                         if (error != OMX_ErrorNone) {
1713                                 Log::getInstance()->log("Video", Log::DEBUG,
1714                                                 "OMX_Flush shed in failed %x", error);
1715
1716                         }
1717
1718                         if (!CommandFinished(omx_vid_deint, OMX_CommandFlush,
1719                                         omx_deint_output_port)) {
1720                                 Log::getInstance()->log("Video", Log::DEBUG,
1721                                                 "flush cmd deint  failed");
1722                         }
1723
1724                         if (!CommandFinished(omx_vid_sched, OMX_CommandFlush,
1725                                         omx_shed_input_port)) {
1726                                 Log::getInstance()->log("Video", Log::DEBUG,
1727                                                 "flush cmd  shed failed");
1728                         }
1729
1730
1731
1732                 }
1733
1734
1735
1736
1737                 error = OMX_SendCommand(omx_vid_rend, OMX_CommandFlush,
1738                                 omx_rend_input_port, NULL);
1739                 if (error != OMX_ErrorNone) {
1740                         Log::getInstance()->log("Video", Log::DEBUG,
1741                                         "OMX_Flush rend in failed %x", error);
1742
1743                 }
1744
1745                 error = OMX_SendCommand(omx_vid_sched, OMX_CommandFlush,
1746                                 omx_shed_output_port, NULL);
1747                 if (error != OMX_ErrorNone) {
1748                         Log::getInstance()->log("Video", Log::DEBUG,
1749                                         "OMX_Flush shed out failed %x", error);
1750
1751                 }
1752
1753
1754
1755                 if (!CommandFinished(omx_vid_rend, OMX_CommandFlush,
1756                                 omx_rend_input_port)) {
1757                         Log::getInstance()->log("Video", Log::DEBUG,
1758                                         "flush cmd shed rend failed");
1759                 }
1760
1761                 if (!CommandFinished(omx_vid_sched, OMX_CommandFlush,
1762                                 omx_shed_output_port)) {
1763                         Log::getInstance()->log("Video", Log::DEBUG,
1764                                         "flush cmd shed rend failed");
1765                 }
1766
1767
1768
1769
1770
1771                 error=OMX_SendCommand(omx_clock,OMX_CommandFlush, omx_clock_output_port, NULL);
1772                 if (error!=OMX_ErrorNone){
1773                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush clock out failed %x", error);
1774
1775                 }
1776
1777                 error=OMX_SendCommand(omx_vid_sched,OMX_CommandFlush, omx_shed_clock_port, NULL);
1778                 if (error!=OMX_ErrorNone){
1779                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush shed clock failed %x", error);
1780
1781                 }
1782
1783                 if (!CommandFinished(omx_clock,OMX_CommandFlush,omx_clock_output_port) ||
1784                         !CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_clock_port)) {
1785                                 Log::getInstance()->log("Video", Log::DEBUG, "flush cmd clock shed failed");
1786                 }
1787
1788
1789
1790
1791                 error = OMX_SendCommand(omx_vid_dec, OMX_CommandFlush,
1792                                 omx_codec_input_port, NULL);
1793                 if (error != OMX_ErrorNone) {
1794                         Log::getInstance()->log("Video", Log::DEBUG,
1795                                         "OMX_Flush codec out failed %x", error);
1796
1797                 }
1798
1799
1800
1801
1802                 DestroyInputBufsOMX();
1803
1804                 //todo flushing
1805                 if (!DisablePort(omx_vid_sched,omx_shed_output_port,true)) {
1806                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 2 ");
1807                 }
1808                 if (!DisablePort(omx_vid_rend,omx_rend_input_port,true)) {
1809                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 1");
1810                 }
1811
1812
1813
1814
1815                 if (!DisablePort(omx_vid_dec,omx_codec_output_port,true)) {
1816                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 6");
1817                 }
1818
1819
1820
1821                 if (!DisablePort(omx_vid_dec,omx_codec_input_port,true)) {
1822                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 7");
1823                 }
1824
1825                 if (dodeint) {
1826                         if (!DisablePort(omx_vid_deint,omx_deint_output_port,true)) {
1827                                 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 6a");
1828                         }
1829
1830
1831
1832                         if (!DisablePort(omx_vid_deint,omx_deint_input_port,true)) {
1833                                 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 7a");
1834                         }
1835                 }
1836
1837
1838
1839                 if (!DisablePort(omx_vid_sched,omx_shed_input_port,true)) {
1840                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 3");
1841                 }
1842
1843                 if (!DisablePort(omx_vid_sched,omx_shed_clock_port,true)) {
1844                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 4");
1845                 }
1846
1847                 if (!DisablePort(omx_clock,omx_clock_output_port,true)) {
1848                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 5");
1849                 }
1850
1851
1852
1853
1854                 error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,NULL,NULL);
1855                 if (error!=OMX_ErrorNone) {
1856                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1857
1858                 }
1859
1860                 if (dodeint) {
1861                         error=OMX_SetupTunnel(omx_vid_deint,omx_deint_input_port,NULL,NULL);
1862                         if (error!=OMX_ErrorNone) {
1863                                 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1864                         }
1865
1866
1867                         error=OMX_SetupTunnel(omx_vid_deint,omx_deint_output_port,NULL,NULL);
1868                         if (error!=OMX_ErrorNone) {
1869                                 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1870                         }
1871                 }
1872
1873                 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_input_port,NULL,NULL);
1874                 if (error!=OMX_ErrorNone) {
1875                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1876
1877                 }
1878
1879
1880                 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_output_port,NULL,NULL);
1881                 if (error!=OMX_ErrorNone) {
1882                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1883
1884                 }
1885
1886                 error=OMX_SetupTunnel(omx_vid_rend,omx_rend_input_port,NULL,NULL);
1887                 if (error!=OMX_ErrorNone) {
1888                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1889
1890                 }
1891
1892
1893                 error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,NULL,NULL);
1894                 if (error!=OMX_ErrorNone) {
1895                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1896
1897                 }
1898
1899                 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_clock_port,NULL,NULL);
1900                 if (error!=OMX_ErrorNone) {
1901                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1902
1903                 }
1904
1905
1906
1907
1908                 error=OMX_FreeHandle(omx_vid_dec);
1909                 error=OMX_FreeHandle(omx_vid_sched);
1910                 error=OMX_FreeHandle(omx_vid_rend);
1911                 if (dodeint) error=OMX_FreeHandle(omx_vid_deint);
1912                 omx_vid_dec=NULL;
1913                 clock_mutex.Unlock();
1914                 destroyClock();
1915                 if (error!=OMX_ErrorNone) {
1916                         Log::getInstance()->log("Video", Log::DEBUG, "FreeHandle failed %d", error);
1917                 }
1918         } else  clock_mutex.Unlock();
1919           Log::getInstance()->log("Video", Log::DEBUG, "leave deallocate codecs OMX");
1920
1921         return 1;
1922 }
1923
1924
1925 void VideoOMX::destroyClock()
1926 {
1927         clock_mutex.Lock();
1928         if (clock_references>0) {
1929                 clock_references--;
1930                 if (clock_references==0) {
1931                         OMX_ERRORTYPE error;
1932                         Log::getInstance()->log("Video", Log::DEBUG, "destroy omx clock");
1933                         error=OMX_FreeHandle(omx_clock);
1934                         if (error!=OMX_ErrorNone) {
1935                                 Log::getInstance()->log("Video", Log::DEBUG, "FreeHandle failed %d", error);
1936                         }
1937
1938                 }
1939         }
1940         clock_mutex.Unlock();
1941
1942 }
1943
1944 int VideoOMX::stop()
1945 {
1946   if (!initted) return 0;
1947   iframemode=false;
1948
1949   //Check if libav mode
1950   DeAllocateCodecsOMX();
1951
1952
1953
1954
1955 //  if (ioctl(fdVideo, AV_SET_VID_STOP, 0) != 0) return 0;
1956   return 1;
1957 }
1958
1959 int VideoOMX::reset()
1960 {
1961   if (!initted) return 0;
1962
1963   iframemode=false;
1964   DeAllocateCodecsOMX();
1965 //  if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0;
1966   return 1;
1967 }
1968
1969 int VideoOMX::pause()
1970 {
1971   if (!initted) return 0;
1972   Log::getInstance()->log("Video", Log::DEBUG, "enter pause");
1973   if (!paused) {
1974           paused=true;
1975           //maybe also change omx clock?
1976           pausetimecode=GetCurrentSystemTime();
1977
1978   }
1979   return 1;
1980 }
1981
1982 int VideoOMX::unPause() // FIXME get rid - same as play!! Not here!
1983 {
1984   if (!initted) return 0;
1985   Log::getInstance()->log("Video", Log::DEBUG, "enter unpause");
1986
1987   if (paused) {
1988           playbacktimeoffset+=GetCurrentSystemTime()-pausetimecode;
1989           paused=false; // may be also change omx clock
1990   }
1991
1992   return 1;
1993 }
1994
1995 int VideoOMX::fastForward()
1996 {
1997   if (!initted) return 0;
1998
1999 //  if (ioctl(fdVideo, AV_SET_VID_libavWD, 1) != 0) return 0;
2000   return 1;
2001 }
2002
2003 int VideoOMX::unFastForward()
2004 {
2005   if (!initted) return 0;
2006
2007 //  if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; // don't need this.
2008
2009  //// if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
2010   return 1;
2011 }
2012
2013 int VideoOMX::attachFrameBuffer()
2014 {
2015   if (!initted) return 0;
2016
2017 //  if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
2018   return 1;
2019 }
2020
2021 int VideoOMX::blank(void)
2022 {
2023 //  if (ioctl(fdVideo, AV_SET_VID_FB, 1) != 0) return 0;
2024 //  if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
2025   return 1;
2026 }
2027
2028 ULLONG VideoOMX::getCurrentTimestamp()
2029 {
2030   if (iframemode) return 0;
2031   return cur_pts;
2032 }
2033
2034 // to be removed
2035 /*
2036 ULONG VideoOMX::timecodeToFrameNumber(ULLONG timecode)
2037 {
2038   if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
2039   else               return (ULONG)(((double)timecode / (double)90000) * (double)30);
2040 }
2041
2042 */
2043 #ifdef DEV
2044 int VideoOMX::test()
2045 {
2046   return 0;
2047
2048 //  ULLONG stc = 0;
2049 //  return ioctl(fdVideo, AV_SET_VID_STC, &stc);
2050 /*
2051  // reset();
2052   return 1;
2053 */
2054 }
2055
2056 int VideoOMX::test2()
2057 {
2058   return 0;
2059 }
2060 #endif
2061
2062
2063
2064 long long VideoOMX::SetStartOffset(long long curreftime, bool *rsync)
2065 {
2066   *rsync=false;
2067   if (offsetnotset) {
2068     startoffset=curreftime;//offset is set for audio
2069     offsetnotset=false;
2070     offsetvideonotset=false;
2071   } else {
2072     if (offsetvideonotset) {
2073       offsetvideonotset=false;
2074       *rsync=true;
2075     } else {
2076       if ( (curreftime-lastrefvideotime)>10000000LL
2077         || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync
2078         startoffset+=curreftime-lastrefvideotime;
2079         lastrefaudiotime+=curreftime-lastrefvideotime;
2080         //*rsync=true;
2081         offsetaudionotset=true;
2082
2083       }
2084     }
2085
2086   }
2087
2088   lastrefvideotime=curreftime;
2089
2090   return startoffset;
2091
2092 }
2093
2094 long long VideoOMX::SetStartAudioOffset(long long curreftime, bool *rsync)
2095 {
2096   *rsync=false;
2097   if (offsetnotset) {
2098     startoffset=curreftime;
2099     offsetnotset=false;
2100     offsetaudionotset=false;
2101   }else {
2102     if (offsetaudionotset) {
2103       offsetaudionotset=false;
2104       *rsync=true;
2105     } else {
2106       if ( (curreftime-lastrefaudiotime)>10000000LL
2107         || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync
2108         startoffset+=curreftime-lastrefaudiotime;
2109         lastrefvideotime+=curreftime-lastrefaudiotime;
2110         //*rsync=true;
2111         offsetvideonotset=true;
2112
2113       }
2114     }
2115
2116   }
2117   lastrefaudiotime=curreftime;
2118   return startoffset;
2119
2120 }
2121
2122 void VideoOMX::ResetTimeOffsets() {
2123   offsetnotset=true; //called from demuxer
2124   offsetvideonotset=true;
2125   offsetaudionotset=true;
2126   startoffset=0;
2127   lastrefaudiotime=0;
2128   lastrefvideotime=0;
2129   lastreftimeOMX=0;
2130   lastreftimePTS=0;
2131   cur_pts=0;
2132 }
2133
2134 long long VideoOMX::GetCurrentSystemTime()
2135 {
2136         struct timespec ts;
2137         clock_gettime(CLOCK_MONOTONIC, &ts);
2138         return ts.tv_sec*10000000LL+ts.tv_nsec/100LL;
2139 }
2140
2141 void VideoOMX::WaitUntil(long long time)
2142 {
2143         struct timespec interval;
2144         interval.tv_sec=time/10000000LL;
2145         interval.tv_nsec=(time %10000000LL)*100LL;
2146         while (clock_nanosleep(CLOCK_MONOTONIC,TIMER_ABSTIME,&interval,NULL)==EINTR) {
2147                 //Log::getInstance()->log("Video", Log::DEBUG, "Wait until multi");
2148
2149         };
2150 }
2151
2152 bool VideoOMX::FrameSkip(long long pts)
2153 {
2154         //ok first calculate the absolute time
2155         bool skip=false;
2156         long long target_time=pts-playbacktimeoffset;
2157         // we have to wait untile the next frame
2158         long long offset=Demuxer::getInstance()->getFrameRate();
2159         if (offset==0) offset=25;
2160         offset=-2*10000000LL/offset;
2161         target_time+=offset;
2162         long long current_time=GetCurrentSystemTime();
2163         if (!skipping) {
2164                 if ((target_time-current_time)<-400000LL) {
2165                         skip=true; // we are too slow
2166                         skipping=true;
2167                 /*      Log::getInstance()->log("Video", Log::DEBUG,
2168                                                                                                                 "Skipping frames1 %lld %lld %d",target_time-current_time,pts,Demuxer::getInstance()->getFrameRate());
2169                         Log::getInstance()->log("Video", Log::DEBUG, "skip detail pts: %lld target: %lld sys: %lld off: %lld diff %lld",pts,target_time,current_time,offset,
2170                                                 target_time-current_time);*/
2171                 }  else {
2172                         skipping=false;
2173                 }
2174         } else {
2175                 if ((target_time - current_time) < 0000LL) { //skip a bit more
2176                         skip = true; // we are too slow
2177                         skipping = true;
2178 /*                      Log::getInstance()->log("Video", Log::DEBUG,"Skipping frames2 %lld %lld %d",target_time-current_time,pts,Demuxer::getInstance()->getFrameRate());
2179                         Log::getInstance()->log("Video", Log::DEBUG, "skip detail pts: %lld target: %lld sys: %lld off: %lld diff %lld",pts,target_time,current_time,offset,
2180                                                                         target_time-current_time);*/
2181                 } else {
2182                         skipping = false;
2183                 }
2184
2185         }
2186
2187         return skip;
2188 }
2189
2190 void VideoOMX::FrameWaitforDisplay(long long pts)
2191 {
2192         //ok first calculate the absolute time
2193         long long target_time=pts-playbacktimeoffset;
2194         // we have to wait untile the next frame
2195         long long offset=Demuxer::getInstance()->getFrameRate();
2196         long long current_time=GetCurrentSystemTime();
2197         if (offset==0) offset=25;
2198         offset=-2*10000000LL/offset;
2199         target_time+=offset;
2200         //Log::getInstance()->log("Video", Log::DEBUG, "Wait for display pts: %lld tg: %lld sys: %lld off: %lld diff %lld po: %lld",pts,target_time,current_time,offset,
2201         //                      target_time-current_time,playbacktimeoffset);
2202         if ((target_time-current_time)>1000000LL) target_time=current_time+1000000LL; // something is wrong do not wait too long
2203         //Log::getInstance()->log("Video", Log::DEBUG, "Wait for display pts: %lld tg: %lld sys: %lld off: %lld diff %lld po: %lld",pts,target_time,current_time,offset,
2204         //              target_time-current_time,playbacktimeoffset);
2205
2206         WaitUntil(target_time);
2207         //Log::getInstance()->log("Video", Log::DEBUG, "Wait for display out %lld",GetCurrentSystemTime());
2208 }
2209
2210 void VideoOMX::AdjustAudioPTS(long long pts)
2211 {
2212         long long newplaybacktimeoffset=pts-GetCurrentSystemTime();
2213 /*      if ((newplaybacktimeoffset-1000000LL)>playbacktimeoffset
2214             || (newplaybacktimeoffset+1000000LL)<playbacktimeoffset) {
2215                 Log::getInstance()->log("Video", Log::DEBUG, "Adjust Playbackoffsettime o: %lld n: %lld",
2216                                 playbacktimeoffset,newplaybacktimeoffset);*/
2217                 playbacktimeoffset=newplaybacktimeoffset;
2218
2219         //}
2220 }
2221
2222 void VideoOMX::threadPostStopCleanup()
2223 {
2224         //Doing nothing
2225         //goo;
2226         Log::getInstance()->log("Video", Log::DEBUG,
2227                                                                                                 "end thread");
2228 }
2229
2230
2231 void VideoOMX::threadMethod()
2232 {
2233         Log::getInstance()->log("Video", Log::DEBUG,
2234                                                                                 "start thread");
2235         while (true) {
2236
2237                 OMX_BUFFERHEADERTYPE* pict=NULL;
2238                 long long time;
2239                 bool islast;
2240                 if (!paused) {
2241                         input_bufs_omx_mutex.Lock();
2242                         if (input_bufs_omx_present.size()>0) {
2243                                 cur_pts=input_time_pts.front();
2244                                 pict=input_bufs_omx_present.front();
2245                                 time=input_time_present.front();
2246                                 islast=input_is_last.front();
2247                                 input_bufs_omx_present.pop_front();
2248                                 input_time_present.pop_front();
2249                                 input_time_pts.pop_front();
2250                                 input_is_last.pop_front();
2251                         }
2252                         input_bufs_omx_mutex.Unlock();
2253                 }
2254
2255                 if ( pict) {
2256                         //Log::getInstance()->log("Video", Log::DEBUG,
2257                         //                                                                                      "Got pict");
2258                         if (time!=0 && FrameSkip(time) && !(pict->nFlags &OMX_BUFFERFLAG_STARTTIME)) {
2259
2260                                 input_bufs_omx_mutex.Lock();
2261                                 input_bufs_omx_free.push_back(pict);
2262                                 input_bufs_omx_mutex.Unlock();
2263                                 //Log::getInstance()->log("Video", Log::DEBUG, "threadMethod Frameskip");
2264
2265                         } else {
2266                         //      Log::getInstance()->log("Video", Log::DEBUG,
2267                                 //                                                                      "prot empty this buffer in");
2268                                 OMX_ERRORTYPE error = ProtOMXEmptyThisBuffer(omx_vid_dec, pict);
2269                                 if (error != OMX_ErrorNone) {
2270                                         Log::getInstance()->log("Video", Log::DEBUG,
2271                                                         "OMX_EmptyThisBuffer failed %x", error);
2272                                 }
2273                                 //Log::getInstance()->log("Video", Log::DEBUG,
2274                                         //                                                                                                      "prot empty this buffer out");
2275                                 if (deint_first_frame && dodeint) DeinterlaceFix();
2276                                 if (islast) FrameWaitforDisplay(time);
2277                         }
2278                 } else {
2279                         MILLISLEEP(5);
2280                 }
2281
2282                 threadCheckExit();
2283         }
2284         Log::getInstance()->log("Video", Log::DEBUG,
2285                                                                                         "end thread");
2286 }
2287
2288 void VideoOMX::DeinterlaceFix()
2289 {
2290
2291         Demuxer* demux=Demuxer::getInstance();
2292         clock_mutex.Lock();
2293         OMX_ERRORTYPE error;
2294         OMX_PARAM_PORTDEFINITIONTYPE port_def_type;
2295         memset(&port_def_type,0,sizeof(port_def_type));
2296         port_def_type.nSize=sizeof(port_def_type);
2297         port_def_type.nVersion.nVersion=OMX_VERSION;
2298         port_def_type.nPortIndex=omx_codec_output_port;
2299
2300         error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type);
2301         if (error != OMX_ErrorNone) {
2302                 Log::getInstance()->log("Video", Log::DEBUG,
2303                                 "OMX_IndexParamPortDefinition fix failed %x", error);
2304                 clock_mutex.Unlock();
2305                 return;
2306         }
2307
2308         if (port_def_type.format.video.nFrameWidth == demux->getHorizontalSize()
2309                         && port_def_type.format.video.nFrameHeight == demux->getVerticalSize()){
2310                 Log::getInstance()->log("Video", Log::DEBUG,
2311                                                         "Deinit first frame fix");
2312                 deint_first_frame=false;
2313
2314                 WaitForEvent(omx_vid_dec,OMX_EventPortSettingsChanged);
2315                 DisablePort(omx_vid_dec,omx_codec_output_port,false);
2316                 DisablePort(omx_vid_sched,omx_shed_input_port,false);
2317                 DisablePort(omx_vid_deint,omx_deint_output_port,false);
2318                 DisablePort(omx_vid_deint,omx_deint_input_port,false);
2319
2320                 port_def_type.nPortIndex=omx_deint_input_port;
2321                 error = OMX_SetParameter(omx_vid_deint, OMX_IndexParamPortDefinition,
2322                                 &port_def_type);
2323                 if (error != OMX_ErrorNone) {
2324                         Log::getInstance()->log("Video", Log::DEBUG,
2325                                         "Set OMX_IndexParamPortDefinition1 failed %x", error);
2326                         clock_mutex.Unlock();
2327                         return;
2328                 }
2329
2330                 port_def_type.nPortIndex=omx_deint_output_port;
2331                 error = OMX_SetParameter(omx_vid_deint, OMX_IndexParamPortDefinition,
2332                                 &port_def_type);
2333                 if (error != OMX_ErrorNone) {
2334                         Log::getInstance()->log("Video", Log::DEBUG,
2335                                         "Set OMX_IndexParamPortDefinition2 failed %x", error);
2336                         clock_mutex.Unlock();
2337                         return;
2338                 }
2339
2340
2341                 EnablePort(omx_vid_dec,omx_codec_output_port,false);
2342                 EnablePort(omx_vid_deint,omx_deint_input_port,false);
2343                 EnablePort(omx_vid_deint,omx_deint_output_port,false);
2344                 EnablePort(omx_vid_sched,omx_shed_input_port,false);
2345         }
2346         clock_mutex.Unlock();
2347
2348
2349 }
2350
2351
2352 void VideoOMX::PutBufferToPres(OMX_BUFFERHEADERTYPE* buffer, long long time, long long pts,bool islast)
2353 {
2354         input_bufs_omx_mutex.Lock();
2355         input_bufs_omx_present.push_back(buffer);
2356         input_time_present.push_back(time);
2357         input_time_pts.push_back(pts);
2358         input_is_last.push_back(islast);
2359         input_bufs_omx_mutex.Unlock();
2360
2361 }
2362
2363 OMX_ERRORTYPE VideoOMX::ProtOMXEmptyThisBuffer(OMX_HANDLETYPE handle, OMX_BUFFERHEADERTYPE* buffer)
2364 {
2365         // protect the call to empty this buffer
2366         int oldcancelstate;
2367         int oldcanceltype;
2368         pthread_testcancel();
2369         pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldcancelstate);
2370         pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldcanceltype);
2371         clock_mutex.Lock();
2372         OMX_ERRORTYPE ret_val;
2373         ret_val=OMX_EmptyThisBuffer(handle,buffer);
2374         clock_mutex.Unlock();
2375         pthread_setcancelstate(oldcancelstate, NULL);
2376         pthread_setcanceltype(oldcanceltype, NULL);
2377         pthread_testcancel();
2378         return ret_val;
2379 }
2380
2381 void VideoOMX::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
2382 {
2383         
2384         mediapackets.clear();
2385         list<MediaPacket>::const_iterator begin=mplist.begin();
2386         list<MediaPacket>::const_iterator itty=mplist.begin();
2387         advance(itty,min(mplist.size(),10));
2388         mediapackets.insert(mediapackets.begin(),begin,itty);//front
2389         
2390 }
2391
2392 UINT VideoOMX::DeliverMediaSample(UCHAR* buffer, UINT *samplepos)
2393 {
2394         int consumed=0;
2395         while (consumed<mediapackets.size()) {
2396             DeliverMediaPacket(mediapackets[consumed], buffer, samplepos);
2397             if (*samplepos == mediapackets[consumed].length) {
2398                 *samplepos = 0;
2399                 consumed++;
2400                 //return 1;
2401             } else return consumed;
2402         }
2403         return consumed;
2404 }
2405
2406 UINT VideoOMX::DeliverMediaPacket(MediaPacket packet,
2407                 const UCHAR* buffer,
2408                 UINT *samplepos)
2409 {
2410         if (packet.type == MPTYPE_VIDEO_H264)
2411         {
2412                 h264=true;
2413         }
2414         else
2415         {
2416                 h264=false;
2417         }
2418
2419
2420         //Later add fail back code for libav
2421 /*      if (!videoon) {
2422                 *samplepos+=packet.length;
2423                 return packet.length;
2424         }*/
2425
2426
2427         if (!omx_running) return 0; // if we are not runnig do not do this
2428         if (paused) return 0; //Block if we pause
2429
2430         if (packet.synched && FrameSkip(packet.presentation_time)) {
2431                 *samplepos=packet.length;
2432                 Log::getInstance()->log("Video", Log::DEBUG, "DeliverMediaPacketOMX Frameskip");
2433                                 *samplepos=packet.length;
2434                 return packet.length;
2435         }
2436         //long long current_media_time=GetCurrentSystemTime()+playbacktimeoffset;
2437 /*      if (packet.synched &&
2438                         (packet.presentation_time<0 /*|| // preroll skip frames
2439                         (packet.presentation_time+5000000LL)<(current_media_time)*)) { // we are late skip
2440                 Log::getInstance()->log("Video", Log::DEBUG, "DeliverMediaPacketOMX Preroll or too late %lld %lld; %lld", packet.presentation_time,current_media_time,playbacktimeoffset);
2441                 *samplepos=packet.length;
2442                 return packet.length;
2443         }*/
2444
2445         OMX_ERRORTYPE error;
2446
2447         /*First Check, if we have an video sample*/
2448         if (iframemode) {
2449                 //samplepos=0;
2450                 MILLISLEEP(10);
2451                 return 0; //Not in iframe mode!
2452         }
2453
2454         UINT headerstrip=0;
2455         if (packet.disconti) {
2456                 firstsynched=false;
2457                 if (cur_input_buf_omx) {
2458                         PutBufferToPres(cur_input_buf_omx, lastreftimeOMX,lastreftimePTS, true);
2459                         cur_input_buf_omx=NULL;
2460                 }
2461         }
2462
2463         /*Inspect PES-Header */
2464
2465 //      OMX_STATETYPE temp_state;
2466 //      OMX_GetState(omx_vid_dec,&temp_state);
2467
2468         if (*samplepos==0) {//stripheader
2469                 headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
2470         //      if (h264) Log::getInstance()->log("Video", Log::DEBUG, "PES info %x %x %x %x",
2471         //                      buffer[packet.pos_buffer+0],buffer[packet.pos_buffer+1],buffer[packet.pos_buffer+2],buffer[packet.pos_buffer+3]);
2472                 *samplepos+=headerstrip;
2473                 if ( packet.synched ) {
2474                         if (cur_input_buf_omx) {
2475                                 cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_ENDOFFRAME;
2476                                 PutBufferToPres(cur_input_buf_omx, lastreftimeOMX,lastreftimePTS,true);
2477                                 cur_input_buf_omx=NULL;//write out old data
2478
2479
2480                         }
2481                         firstsynched=true;
2482                 } else {
2483                         if (!firstsynched) {//
2484                                 *samplepos=packet.length;//if we have not processed at least one
2485                                 return packet.length;//synched packet ignore it!
2486                         }
2487                 }
2488         }
2489
2490         if (!cur_input_buf_omx) {
2491                 input_bufs_omx_mutex.Lock();
2492                 if (input_bufs_omx_free.size()==0) {
2493                         input_bufs_omx_mutex.Unlock();
2494                         //Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket no free sample");
2495                         return 0; // we do not have a free media sample
2496
2497                 }
2498                 cur_input_buf_omx=input_bufs_omx_free.front();
2499                 cur_input_buf_omx->nFilledLen=0;
2500                 cur_input_buf_omx->nOffset=0;
2501                 cur_input_buf_omx->nTimeStamp=0;
2502                 input_bufs_omx_free.pop_front();
2503                 input_bufs_omx_mutex.Unlock();
2504         }
2505
2506
2507
2508
2509         if (cur_input_buf_omx->nFilledLen==0) {//will only be changed on first packet
2510                 if (packet.synched) {
2511                 //      Log::getInstance()->log("Video", Log::DEBUG, "packet synched marker");
2512
2513                         //lastreftimePTS=packet.pts;
2514                    if (omx_first_frame) { // TODO time
2515                            cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_STARTTIME;
2516                            Log::getInstance()->log("Video", Log::DEBUG, "Starttime");
2517                            omx_first_frame=false;
2518                    } else {
2519                            //cur_input_buf_omx->nFlags=0;
2520                            cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_TIME_UNKNOWN;
2521                    }
2522                    lastreftimeOMX=packet.presentation_time;
2523                   // Log::getInstance()->log("Video", Log::DEBUG, "Time code %lld pts %lld", lastreftimeOMX,packet.pts);
2524                    lastreftimePTS=packet.pts;
2525                    cur_input_buf_omx->nTimeStamp=0;//lastreftimeOMX; // the clock component is faulty;
2526                 }
2527                 else
2528                 {
2529                         cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
2530                         cur_input_buf_omx->nTimeStamp=0;
2531                         //Log::getInstance()->log("Video", Log::DEBUG, "packet unsynched marker");
2532                         //  ms->SetSyncPoint(TRUE);
2533                 }
2534                 if (packet.disconti) cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_DISCONTINUITY;
2535
2536
2537
2538         }
2539         unsigned int haveToCopy=packet.length-*samplepos;
2540
2541         while (haveToCopy> (cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen)) {
2542                 //Log::getInstance()->log("Video", Log::DEBUG, "Big buffer %d %d %d",packet.length,cur_input_buf_omx->nAllocLen,cur_input_buf_omx->nFilledLen);
2543                 unsigned int cancopy=cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen;
2544                 memcpy(cur_input_buf_omx->pBuffer+cur_input_buf_omx->nFilledLen,buffer+packet.pos_buffer+*samplepos,cancopy);
2545                 haveToCopy-=cancopy;
2546                 cur_input_buf_omx->nFilledLen+=cancopy;
2547                 *samplepos+=cancopy;
2548                 // push old buffer out
2549
2550                 PutBufferToPres(cur_input_buf_omx, lastreftimeOMX,lastreftimePTS,false);
2551                 cur_input_buf_omx=NULL;
2552                 // get5 new buffer
2553                 input_bufs_omx_mutex.Lock();
2554                 if (input_bufs_omx_free.size()==0) {
2555                         input_bufs_omx_mutex.Unlock();
2556                 //      Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket no free sample2");
2557                         return *samplepos; // we do not have a free media sample
2558                 }
2559                 cur_input_buf_omx=input_bufs_omx_free.front();
2560                 cur_input_buf_omx->nFilledLen=0;
2561                 cur_input_buf_omx->nOffset=0;
2562                 cur_input_buf_omx->nTimeStamp=0;
2563                 input_bufs_omx_free.pop_front();
2564                 input_bufs_omx_mutex.Unlock();
2565
2566                 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
2567
2568         }
2569         memcpy(cur_input_buf_omx->pBuffer+cur_input_buf_omx->nFilledLen,
2570                         buffer+packet.pos_buffer+*samplepos,haveToCopy);
2571         cur_input_buf_omx->nFilledLen+=haveToCopy;
2572
2573
2574
2575         *samplepos+=haveToCopy;
2576
2577         return *samplepos;
2578
2579 }
2580
2581
2582
2583
2584 bool VideoOMX::displayIFrame(const UCHAR* buffer, UINT length) {
2585         if (!omx_running) return false;
2586         if (!iframemode)
2587                 EnterIframePlayback();
2588
2589         int haveToCopy = length;
2590
2591         if (!cur_input_buf_omx) {
2592                 input_bufs_omx_mutex.Lock();
2593                 if (input_bufs_omx_free.size() == 0) {
2594                         input_bufs_omx_mutex.Unlock();
2595                 //      Log::getInstance()->log("Video", Log::DEBUG,
2596                         //              "Deliver MediaPacket no free sample");
2597                         return false; // we do not have a free media sample
2598
2599                 }
2600                 cur_input_buf_omx = input_bufs_omx_free.front();
2601                 cur_input_buf_omx->nFilledLen = 0;
2602                 cur_input_buf_omx->nOffset = 0;
2603                 cur_input_buf_omx->nTimeStamp = 0;
2604                 input_bufs_omx_free.pop_front();
2605                 input_bufs_omx_mutex.Unlock();
2606         }
2607
2608         int read_pos = 0;
2609         unsigned int pattern, packet_length;
2610         unsigned int headerstrip = 0;
2611         bool first = true;
2612         if (length < 4){
2613                 return false;
2614         }
2615         //Now we strip the pes header
2616         pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);
2617         while (read_pos + 7 <= length) {
2618                 pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos + 3];
2619                 if (pattern < 0x000001E0 || pattern > 0x000001EF) {
2620                         read_pos++;
2621                         continue;
2622                 } else {
2623                         headerstrip = buffer[read_pos + 8] + 9/*is this right*/;
2624                         packet_length = ((buffer[read_pos + 4] << 8)
2625                                         | (buffer[read_pos + 5])) + 6;
2626                         if (read_pos + packet_length > length)
2627                                 read_pos = length;
2628                         else {
2629                                 if ((headerstrip < packet_length)
2630                                                 && (cur_input_buf_omx->nFilledLen + packet_length
2631                                                                 - headerstrip) > cur_input_buf_omx->nAllocLen) {
2632                                         if (first) {
2633                                                 cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_STARTTIME;
2634
2635                                         } else {
2636                                                 cur_input_buf_omx->nFlags
2637                                                                 |= OMX_BUFFERFLAG_TIME_UNKNOWN;
2638
2639                                         }
2640                                         cur_input_buf_omx->nTimeStamp = 0;
2641                                         PutBufferToPres(cur_input_buf_omx, 0,0,false);
2642                                         cur_input_buf_omx = NULL;
2643
2644                                         if (!cur_input_buf_omx) {
2645                                                 int count = 0;
2646                                                 while (count < 100 && omx_running && iframemode) {
2647                                                         count++;
2648
2649                                                         input_bufs_omx_mutex.Lock();
2650                                                         if (input_bufs_omx_free.size() == 0) {
2651                                                                 input_bufs_omx_mutex.Unlock();
2652                                         //                      Log::getInstance()->log("Video", Log::DEBUG,
2653                                                 //                              "Ifrane no free sample");
2654                                                                 MILLISLEEP(5);
2655                                                                 if (!omx_running) return false;
2656                                                                 continue;
2657                                                         }
2658                                                         cur_input_buf_omx = input_bufs_omx_free.front();
2659                                                         cur_input_buf_omx->nFilledLen = 0;
2660                                                         cur_input_buf_omx->nOffset = 0;
2661                                                         cur_input_buf_omx->nTimeStamp = 0;
2662                                                         input_bufs_omx_free.pop_front();
2663                                                         input_bufs_omx_mutex.Unlock();
2664                                                         break;
2665                                                 }
2666                                                 if (!cur_input_buf_omx)
2667                                                         return false;
2668                                         }
2669
2670                                 }
2671                                 if (packet_length > headerstrip) {
2672                                         memcpy(
2673                                                         cur_input_buf_omx->pBuffer
2674                                                                         + cur_input_buf_omx->nFilledLen,
2675                                                         buffer + read_pos + headerstrip,
2676                                                         packet_length - headerstrip);
2677                                         cur_input_buf_omx->nFilledLen += packet_length
2678                                                         - headerstrip;
2679                                 }
2680                                 read_pos += packet_length;
2681
2682                                 pattern = (buffer[read_pos] << 16)
2683                                                 | (buffer[read_pos + 1] << 8) | (buffer[read_pos + 2]);
2684                         }
2685                 }
2686         }
2687
2688         if (first) {
2689                 cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_STARTTIME;
2690
2691         } else {
2692                 cur_input_buf_omx->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
2693
2694         }
2695         cur_input_buf_omx->nTimeStamp = 0;
2696         
2697         PutBufferToPres(cur_input_buf_omx, 0,0,false);
2698         cur_input_buf_omx = NULL;
2699
2700
2701         MILLISLEEP(40); //Block a bit
2702         return true;
2703 }
2704
2705 int VideoOMX::EnterIframePlayback()
2706 {
2707         if (cur_input_buf_omx) {
2708                 PutBufferToPres(cur_input_buf_omx, lastreftimeOMX, lastreftimePTS,true);
2709                 cur_input_buf_omx = NULL;
2710         }
2711         input_bufs_omx_mutex.Lock();
2712         while (input_bufs_omx_present.size()) {
2713                 input_bufs_omx_free.push_back(input_bufs_omx_present.front());
2714                 input_bufs_omx_present.pop_front();
2715         }
2716         input_time_present.clear();
2717         input_time_pts.clear();
2718         input_is_last.clear();
2719         input_bufs_omx_mutex.Unlock();
2720
2721         iframemode=true;
2722
2723         return 1;
2724 }
2725