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