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