]> git.vomp.tv Git - vompclient.git/blob - videoomx.cc
Move video feeding to separate thread and enhance video playback
[vompclient.git] / videoomx.cc
1 /*
2     Copyright 2004-2005 Chris Tallon, 2009 Marten Richter
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "videoomx.h"
22 #include "audioomx.h"
23 #include "mtdraspberry.h"
24 #include "demuxer.h"
25 #include "osdopengl.h"
26
27 // temp
28 #include "log.h"
29
30 //A lot of parts of this file are heavily inspired by xbmc omx implementations
31
32 VideoOMX::VideoOMX() {
33
34         omx_running = false;
35
36         omx_vid_dec = 0;
37         cur_input_buf_omx = NULL;
38         omx_h264 = omx_mpeg2 = true;
39         clock_references = 0;
40
41         offsetnotset = true;
42         offsetvideonotset = true;
43         offsetaudionotset = true;
44         startoffset = 0;
45         lastrefaudiotime = 0;
46         lastrefvideotime = 0;
47         lastreftimeOMX = 0;
48         lastreftimePTS = 0;
49         firstsynched = false;
50
51 }
52
53 VideoOMX::~VideoOMX()
54 {
55   instance = NULL;
56 }
57
58 int VideoOMX::init(UCHAR tformat)
59 {
60   if (initted) return 0;
61   initted = 1;
62
63   if (!setFormat(tformat))           { shutdown(); return 0; }
64   if (!setConnection(COMPOSITERGB))  { shutdown(); return 0; }
65   if (!setAspectRatio(ASPECT4X3))    { shutdown(); return 0; }
66   if (!setMode(NORMAL))              { shutdown(); return 0; }
67   if (!setSource())                  { shutdown(); return 0; }
68   if (!attachFrameBuffer())          { shutdown(); return 0; }
69
70   setTVsize(ASPECT4X3);
71
72
73
74
75
76   //stop();
77
78
79
80   return 1;
81 }
82
83 int VideoOMX::initUsingOSDObjects()
84 {
85
86 // we are called before the audio
87         OMX_ERRORTYPE error;
88         error=OMX_Init();
89         if (error!=OMX_ErrorNone) {
90                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX failed %x", error);
91                 return 0;
92         }
93
94         return 1;
95 }
96
97
98 OMX_ERRORTYPE VideoOMX::EventHandler_OMX(OMX_IN OMX_HANDLETYPE handle,OMX_IN OMX_PTR appdata,
99            OMX_IN OMX_EVENTTYPE event_type,OMX_IN OMX_U32 data1,
100            OMX_IN OMX_U32 data2,OMX_IN OMX_PTR event_data) {
101
102         Log::getInstance()->log("Video", Log::NOTICE, "eventHandler %x %x %x %x %x",handle,event_type,data1,data2,event_data);
103
104         struct VPE_OMX_EVENT  new_event;
105         new_event.handle=handle;
106         new_event.appdata=appdata;
107         new_event.event_type=event_type;
108         new_event.data1=data1;
109         new_event.data2=data2;
110         new_event.event_data=event_data;
111
112         VideoOMX *video=(VideoOMX *)getInstance();
113         video->AddOmxEvent(new_event);
114
115 /*      switch (event_type) {
116         case OMX_EventCmdComplete: {
117
118         } break;
119         }*/
120
121         return OMX_ErrorNone;
122
123 }
124
125 void VideoOMX::AddOmxEvent(VPE_OMX_EVENT  new_event)
126 {
127         omx_event_mutex.Lock();
128     omx_events.push_back(new_event);
129         omx_event_mutex.Unlock();
130 }
131
132
133 OMX_ERRORTYPE VideoOMX::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer){
134
135         //Log::getInstance()->log("Video", Log::NOTICE, "EmptyBufferDone");
136         VideoOMX *video=(VideoOMX *)getInstance();
137         video->ReturnEmptyOMXBuffer(buffer);
138         return OMX_ErrorNone;
139
140 }
141
142 void VideoOMX::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){
143         input_bufs_omx_mutex.Lock();
144 //      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());
145         input_bufs_omx_free.push_back(buffer);
146         //Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size());
147         input_bufs_omx_mutex.Unlock();
148 }
149
150  OMX_ERRORTYPE VideoOMX::FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer) {
151          Log::getInstance()->log("Video", Log::NOTICE, "FillBufferDone");
152         return OMX_ErrorNone;
153 }
154
155
156
157 int VideoOMX::shutdown()
158 {
159   if (!initted) return 0;
160   initted = 0;
161
162   DeAllocateCodecsOMX();
163   OMX_Deinit();
164   return 1;
165 }
166
167
168 int VideoOMX::setTVsize(UCHAR ttvsize)
169 {
170 /*  tvsize = ttvsize;
171
172   // Override the aspect ratio usage, temporarily use to set the video chip mode
173   if (!setAspectRatio(tvsize))       { shutdown(); return 0; }
174   close(fdVideo);
175   if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
176   if (!setSource())                  { shutdown(); return 0; }
177   if (!attachFramebuffer())          { shutdown(); return 0; }
178
179   // Reopening the fd causes the scart aspect line to go back to 4:3
180   // Set this again to the same as the tv screen size
181   if (!setAspectRatio(tvsize))       { shutdown(); return 0; }
182
183   // mode == LETTERBOX is invalid if the TV is widescreen
184   if (tvsize == ASPECT16X9) setMode(NORMAL);
185 */
186   return 1;
187 }
188
189 int VideoOMX::setDefaultAspect()
190 {
191   return setAspectRatio(tvsize);
192 }
193
194
195
196 int VideoOMX::setFormat(UCHAR tformat)
197 {
198   if (!initted) return 0;
199   if ((tformat != PAL) && (tformat != NTSC)) return 0;
200   format = tformat;
201
202 //  if (ioctl(fdVideo, AV_SET_VID_DISP_FMT, format) != 0) return 0;
203
204   if (format == NTSC)
205   {
206     screenWidth = 720;
207     screenHeight = 480;
208   }
209   if (format == PAL)
210   {
211     screenWidth = 720;
212     screenHeight = 576;
213   }
214
215   return 1;
216 }
217
218 int VideoOMX::setConnection(UCHAR tconnection)
219 {
220   if (!initted) return 0;
221   if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;
222   connection = tconnection;
223
224 //  if (ioctl(fdVideo, AV_SET_VID_OUTPUT, connection) != 0) return 0;
225   return 1;
226 }
227
228 int VideoOMX::setAspectRatio(UCHAR taspectRatio)
229 {
230   if (!initted) return 0;
231   if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
232   aspectRatio = taspectRatio;
233
234   Log::getInstance()->log("Video", Log::DEBUG, "Setting aspect to %i", aspectRatio);
235
236 //  if (ioctl(fdVideo, AV_SET_VID_RATIO, aspectRatio) != 0) return 0;
237   return 1;
238 }
239
240 int VideoOMX::setMode(UCHAR tmode)
241 {
242   if (!initted) return 0;
243
244   if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode
245
246   if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH)
247       && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0;
248   mode = tmode;
249
250 //  if (ioctl(fdVideo, AV_SET_VID_MODE, mode) != 0) return 0;
251   return 1;
252 }
253
254 int VideoOMX::signalOff()
255 {
256 //  if (ioctl(fdVideo, AV_SET_VID_DENC, 0) != 0) return 0;
257   return 1;
258 }
259
260 int VideoOMX::signalOn()
261 {
262 //  if (ioctl(fdVideo, AV_SET_VID_DENC, 1) != 0) return 0;
263   return 1;
264 }
265
266 int VideoOMX::setSource()
267 {
268   if (!initted) return 0;
269
270   // What does this do...
271 //  if (ioctl(fdVideo, AV_SET_VID_SRC, 1) != 0) return 0;
272   return 1;
273 }
274
275 int VideoOMX::setPosition(int x, int y)
276 {
277   if (!initted) return 0;
278
279 //  vid_pos_regs_t pos_d;
280 //  pos_d.x = x;
281 //  pos_d.y = y;
282
283 /*  vid_pos_regs_t pos_d;
284
285   memset(&pos_d, 0, sizeof(pos_d));
286
287   pos_d.dest.y = y;
288   pos_d.dest.x = x;
289 /*
290 typedef struct {
291   int w;
292   int h;
293   int scale;
294   int x1;
295   int y;
296   int x;
297   int y2;
298   int x3;
299   int y3;
300   int x4;
301   int y4;
302 } vid_pos_regs_t;
303 */
304
305 /*
306   pos_d.w = 100;
307   pos_d.h = 30;
308   pos_d.scale = 2;
309   pos_d.x1 = 0;
310   pos_d.y = 100;            // Top left X
311   pos_d.x = 50;            // Top left Y
312   pos_d.y2 = 30;
313   pos_d.x3 = 60;
314   pos_d.y3 = 90;
315   pos_d.x4 = 120;
316   pos_d.y4 = 150;
317 */
318
319 //  if (ioctl(fdVideo, AV_SET_VID_POSITION, &pos_d) != 0) return 0;
320   return 1;
321 }
322
323 int VideoOMX::sync()
324 {
325   if (!initted) return 0;
326
327 //  if (ioctl(fdVideo, AV_SET_VID_SYNC, 2) != 0) return 0;
328   return 1;
329 }
330
331
332 int VideoOMX::play() {
333         if (!initted)
334                 return 0;
335         iframemode = false;
336         Log::getInstance()->log("Video", Log::DEBUG, "enter play");
337
338         if (AllocateCodecsOMX()) {
339                 return 1;
340                 // Otherwise fall back to libav
341         } else {
342                 if (h264) {
343                         omx_h264 = false;
344                         Log::getInstance()->log("Video", Log::NOTICE,
345                                         "Allocate Codecs OMX failed assume h264 unsupported");
346                 } else {
347                         omx_mpeg2 = false;
348                         Log::getInstance()->log("Video", Log::NOTICE,
349                                         "Allocate Codecs OMX failed assume mpeg2 unsupported");
350                 }
351         }
352
353         return 0;
354
355 }
356
357
358 int VideoOMX::initClock()
359 {
360         OMX_ERRORTYPE error;
361         clock_mutex.Lock();
362         if (clock_references==0)
363         {
364
365                 static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
366                 omx_events.clear();
367
368                 error=OMX_GetHandle(&omx_clock,VPE_OMX_CLOCK,NULL,&callbacks);
369
370                 if (error!=OMX_ErrorNone) {
371                         Log::getInstance()->log("Video", Log::DEBUG, "Init OMX clock failed %x", error);
372                         clock_mutex.Unlock();
373                         DeAllocateCodecsOMX();
374                         return 0;
375                 }
376
377                 /* TODO Clock config to separate method */
378                 OMX_PORT_PARAM_TYPE p_param;
379                 memset(&p_param,0,sizeof(p_param));
380                 p_param.nSize=sizeof(p_param);
381                 p_param.nVersion.nVersion=OMX_VERSION;
382                 error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param);
383                 if (error!=OMX_ErrorNone) {
384                         Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error);
385                         clock_mutex.Unlock();
386                         DeAllocateCodecsOMX();
387                         return 0;
388                 }
389                 omx_clock_output_port=p_param.nStartPortNumber;
390
391                 for (unsigned int i=0;i<p_param.nPorts;i++) {
392                         if (!DisablePort(omx_clock,p_param.nStartPortNumber+i,true) ) {
393                                 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX clock failed %d",i);
394                                 clock_mutex.Unlock();
395                                 DeAllocateCodecsOMX();
396                                 return 0;
397                         }
398                 }
399
400
401
402
403         }
404         Log::getInstance()->log("Video", Log::DEBUG, "init omx clock %x %x",this,omx_clock);
405         clock_references++;
406         clock_mutex.Unlock();
407         return 1;
408 }
409
410 int VideoOMX::getClockAudioandInit(OMX_HANDLETYPE *p_omx_clock,OMX_U32 *p_omx_clock_output_port)
411 {
412         OMX_ERRORTYPE error;
413         *p_omx_clock=NULL;
414         *p_omx_clock_output_port=0;
415
416         if (!initClock()) {
417                 return 0;
418         }
419         clock_mutex.Lock();
420
421         OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refclock;
422         memset(&refclock,0,sizeof(refclock));
423         refclock.nSize=sizeof(refclock);
424         refclock.nVersion.nVersion=OMX_VERSION;
425
426         refclock.eClock=OMX_TIME_RefClockAudio;
427
428         //refclock.eClock=OMX_TIME_RefClockVideo;
429         error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeActiveRefClock,&refclock);
430         if (error!=OMX_ErrorNone){
431                 Log::getInstance()->log("Video", Log::DEBUG, "Clock OMX_IndexConfigTimeActiveRefClock failed %x", error);
432                 clock_mutex.Unlock();
433                 DeAllocateCodecsOMX();
434                 return 0;
435         }
436
437         OMX_PORT_PARAM_TYPE p_param;
438         memset(&p_param,0,sizeof(p_param));
439         p_param.nSize=sizeof(p_param);
440         p_param.nVersion.nVersion=OMX_VERSION;
441         error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param);
442         if (error!=OMX_ErrorNone){
443                 Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error);
444                 clock_mutex.Unlock();
445                 DeAllocateCodecsOMX();
446                 return 0;
447         }
448
449         OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
450         memset(&clock_conf,0,sizeof(clock_conf));
451         clock_conf.nSize=sizeof(clock_conf);
452         clock_conf.nVersion.nVersion=OMX_VERSION;
453         clock_conf.eState=OMX_TIME_ClockStateWaitingForStartTime;
454         clock_conf.nStartTime=0;
455         clock_conf.nOffset=0;
456         if (clock_references==1) clock_conf.nWaitMask=OMX_CLOCKPORT1;
457         else clock_conf.nWaitMask=OMX_CLOCKPORT0|OMX_CLOCKPORT1;
458         error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
459         if (error!=OMX_ErrorNone) {
460                 Log::getInstance()->log("Video", Log::DEBUG, "AuI Clock IndexConfigTimeClockState failed %x", error);
461         }
462
463
464         *p_omx_clock_output_port=p_param.nStartPortNumber+1;
465         *p_omx_clock=omx_clock;
466         clock_mutex.Unlock();
467         return 1;
468 }
469
470 int VideoOMX::getClockVideoandInit()
471 {
472         OMX_ERRORTYPE error;
473
474         if (!initClock()) {
475                 return 0;
476         }
477         clock_mutex.Lock();
478
479         if (clock_references==1) { // only if no audio is attached to this clock!
480                 OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refclock;
481                 memset(&refclock,0,sizeof(refclock));
482                 refclock.nSize=sizeof(refclock);
483                 refclock.nVersion.nVersion=OMX_VERSION;
484
485                 //refclock.eClock=OMX_TIME_RefClockAudio;
486
487                 refclock.eClock=OMX_TIME_RefClockVideo;
488                 error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeActiveRefClock,&refclock);
489                 if (error!=OMX_ErrorNone) {
490                         Log::getInstance()->log("Video", Log::DEBUG, "Clock OMX_IndexConfigTimeActiveRefClock failed %x", error);
491                         clock_mutex.Unlock();
492                         DeAllocateCodecsOMX();
493                         return 0;
494                 }
495         }
496
497         OMX_PORT_PARAM_TYPE p_param;
498         memset(&p_param,0,sizeof(p_param));
499         p_param.nSize=sizeof(p_param);
500         p_param.nVersion.nVersion=OMX_VERSION;
501         error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param);
502         if (error!=OMX_ErrorNone){
503                 Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error);
504                 clock_mutex.Unlock();
505                 DeAllocateCodecsOMX();
506                 return 0;
507         }
508
509
510         OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
511         memset(&clock_conf,0,sizeof(clock_conf));
512         clock_conf.nSize=sizeof(clock_conf);
513         clock_conf.nVersion.nVersion=OMX_VERSION;
514         clock_conf.eState=OMX_TIME_ClockStateWaitingForStartTime;
515         clock_conf.nStartTime=0;
516         clock_conf.nOffset=0;
517         if (clock_references==1) clock_conf.nWaitMask=OMX_CLOCKPORT0;
518         else clock_conf.nWaitMask=OMX_CLOCKPORT0|OMX_CLOCKPORT1;
519         error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
520         if (error!=OMX_ErrorNone) {
521                 Log::getInstance()->log("Video", Log::DEBUG, "VuI Clock IndexConfigTimeClockState failed %x", error);
522         }
523
524         omx_clock_output_port=p_param.nStartPortNumber;
525         clock_mutex.Unlock();
526
527         return 1;
528 }
529
530 void VideoOMX::clockUnpause()
531 {
532         OMX_ERRORTYPE error;
533         clock_mutex.Lock();
534         OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
535         memset(&clock_conf,0,sizeof(clock_conf));
536         clock_conf.nSize=sizeof(clock_conf);
537         clock_conf.nVersion.nVersion=OMX_VERSION;
538         clock_conf.eState=OMX_TIME_ClockStateRunning;
539         clock_conf.nStartTime=0;
540         clock_conf.nOffset=0;
541         clock_conf.nWaitMask=OMX_CLOCKPORT1;
542         error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
543         if (error!=OMX_ErrorNone) {
544                 Log::getInstance()->log("Video", Log::DEBUG, "ClockUnpause IndexConfigTimeClockState failed %x", error);
545         }
546
547         clock_mutex.Unlock();
548 }
549
550
551 void VideoOMX::clockPause()
552 {
553         OMX_ERRORTYPE error;
554         clock_mutex.Lock();
555         OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
556         memset(&clock_conf,0,sizeof(clock_conf));
557         clock_conf.nSize=sizeof(clock_conf);
558         clock_conf.nVersion.nVersion=OMX_VERSION;
559         clock_conf.eState=OMX_TIME_ClockStateStopped;
560         clock_conf.nStartTime=0;
561         clock_conf.nOffset=0;
562         clock_conf.nWaitMask=OMX_CLOCKPORT1;
563         error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
564         if (error!=OMX_ErrorNone) {
565                 Log::getInstance()->log("Video", Log::DEBUG, "ClockUnpause IndexConfigTimeClockState failed %x", error);
566         }
567         clock_mutex.Unlock();
568 }
569
570
571
572 int VideoOMX::AllocateCodecsOMX()
573 {
574         OMX_ERRORTYPE error;
575         static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
576
577         Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX");
578         //Clock, move later to audio including events
579
580         Log::getInstance()->log("Video", Log::DEBUG, "Nmark1 ");
581         if (!getClockVideoandInit()){
582                 return 0;// get the clock and init it if necessary
583         }
584         Log::getInstance()->log("Video", Log::DEBUG, "Nmark2 ");
585
586         if (!idleClock()) {
587                 Log::getInstance()->log("Video", Log::DEBUG, "idleClock failed");
588                 return 0;
589         }
590         /* TODO end */
591
592
593         clock_mutex.Lock();
594         if (h264) {
595                 error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_H264_DECODER,NULL,&callbacks);
596         } else {
597                 error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_MPEG2_DECODER,NULL,&callbacks);
598         }
599
600         if (error!=OMX_ErrorNone){
601                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video decoder failed %x", error);
602                 clock_mutex.Unlock();
603                 DeAllocateCodecsOMX();
604                 return 0;
605         }
606
607
608         Log::getInstance()->log("Video", Log::DEBUG, "Nmark3 ");
609         OMX_PORT_PARAM_TYPE p_param;
610         memset(&p_param,0,sizeof(p_param));
611         p_param.nSize=sizeof(p_param);
612         p_param.nVersion.nVersion=OMX_VERSION;
613         error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamVideoInit,&p_param);
614         if (error!=OMX_ErrorNone){
615                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX h264 decoder OMX_GetParameter failed %x", error);
616                 clock_mutex.Unlock();
617                 DeAllocateCodecsOMX();
618             return 0;
619         }
620         omx_codec_input_port=p_param.nStartPortNumber;
621         omx_codec_output_port=p_param.nStartPortNumber+1;
622
623         if (!DisablePort(omx_vid_dec,omx_codec_input_port) || !DisablePort(omx_vid_dec,omx_codec_output_port)) {
624                 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video decoder failed");
625                 clock_mutex.Unlock();
626                 DeAllocateCodecsOMX();
627                 return 0;
628         }
629
630         Log::getInstance()->log("Video", Log::DEBUG, "Nmark4 ");
631
632         OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE conceal;
633         memset(&conceal,0,sizeof(conceal));
634         conceal.nSize=sizeof(conceal);
635         conceal.nVersion.nVersion=OMX_VERSION;
636         conceal.bStartWithValidFrame=OMX_FALSE;
637
638         error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamBrcmVideoDecodeErrorConcealment,&conceal);
639         if (error!=OMX_ErrorNone){
640                 Log::getInstance()->log("Video", Log::DEBUG, "OMX_IndexParamBrcmVideoDecodeErrorConcealment failed %x", error);
641                 clock_mutex.Unlock();
642                 DeAllocateCodecsOMX();
643                 return 0;
644         }
645
646
647         error=OMX_GetHandle(&omx_vid_sched,VPE_OMX_VIDEO_SCHED,NULL,&callbacks);
648         if (error!=OMX_ErrorNone){
649                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler failed %x", error);
650                 clock_mutex.Unlock();
651                 DeAllocateCodecsOMX();
652                 return 0;
653         }
654
655
656
657         error=OMX_GetParameter(omx_vid_sched,OMX_IndexParamVideoInit,&p_param);
658         if (error!=OMX_ErrorNone){
659                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler OMX_GetParameter failed %x", error);
660                 clock_mutex.Unlock();
661                 DeAllocateCodecsOMX();
662                 return 0;
663         }
664         omx_shed_input_port=p_param.nStartPortNumber;
665         omx_shed_output_port=p_param.nStartPortNumber+1;
666
667
668         error=OMX_GetParameter(omx_vid_sched,OMX_IndexParamOtherInit,&p_param);
669         if (error!=OMX_ErrorNone){
670                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler OMX_GetParameter failed %x", error);
671                 clock_mutex.Unlock();
672                 DeAllocateCodecsOMX();
673                 return 0;
674         }
675         omx_shed_clock_port=p_param.nStartPortNumber;
676         Log::getInstance()->log("Video", Log::DEBUG, "scheduler ports %d %d %d ",omx_shed_input_port,omx_shed_output_port,omx_shed_clock_port);
677
678
679         if (!DisablePort(omx_vid_sched,omx_shed_input_port,true) || !DisablePort(omx_vid_sched,omx_shed_output_port,true)
680                         || !DisablePort(omx_vid_sched,omx_shed_clock_port,true)) {
681                 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video shed failed");
682                 clock_mutex.Unlock();
683                 DeAllocateCodecsOMX();
684                 return 0;
685         }
686
687
688         error=OMX_GetHandle(&omx_vid_rend,VPE_OMX_VIDEO_REND,NULL,&callbacks);
689         if (error!=OMX_ErrorNone){
690                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video rend failed %x", error);
691                 clock_mutex.Unlock();
692                 DeAllocateCodecsOMX();
693                 return 0;
694         }
695
696         error=OMX_GetParameter(omx_vid_rend,OMX_IndexParamVideoInit,&p_param);
697         if (error!=OMX_ErrorNone){
698                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video rend OMX_GetParameter failed %x", error);
699                 clock_mutex.Unlock();
700                 DeAllocateCodecsOMX();
701                 return 0;
702         }
703         omx_rend_input_port=p_param.nStartPortNumber;
704         //omx_rend_output_port=p_param.nStartPortNumber+1;
705
706
707         if (!DisablePort(omx_vid_rend,omx_rend_input_port,true) /*|| !DisablePort(omx_vid_rend,omx_rend_output_port)*/
708                                 ) {
709                 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video rend failed");
710                 clock_mutex.Unlock();
711                 DeAllocateCodecsOMX();
712                 return 0;
713         }
714
715         //Setuo chain
716
717
718
719         error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,omx_vid_sched,omx_shed_clock_port);
720         if (error!=OMX_ErrorNone){
721                 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);
722                 clock_mutex.Unlock();
723                 DeAllocateCodecsOMX();
724                 return 0;
725         }
726
727         if (!EnablePort(omx_clock,omx_clock_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_clock_port,false)
728                                         ) {
729                 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX clock shed failed");
730                 clock_mutex.Unlock();
731                 DeAllocateCodecsOMX();
732                 return 0;
733         }
734
735
736         Log::getInstance()->log("Video", Log::DEBUG, "mark2 ");
737         if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) {
738                 Log::getInstance()->log("Video", Log::DEBUG, "vid_sched idle ChangeComponentState");
739                 clock_mutex.Unlock();
740                 DeAllocateCodecsOMX();
741                 return 0;
742         }
743
744
745
746         Log::getInstance()->log("Video", Log::DEBUG, "mark1 ");
747         if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_clock_port)) {
748                 clock_mutex.Unlock();
749                 DeAllocateCodecsOMX();
750                 return 0;
751         }
752
753
754
755
756         Log::getInstance()->log("Video", Log::DEBUG, "mark1 special ");
757         if ( !CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port)) {
758                 clock_mutex.Unlock();
759                 DeAllocateCodecsOMX();
760                 return 0;
761         }
762         clock_mutex.Unlock();
763
764
765         Log::getInstance()->log("Video", Log::DEBUG, "mark1b ");
766
767
768 /*      error=OMX_SendCommand(omx_vid_dec,OMX_CommandStateSet,OMX_StateIdle,0);
769         if (error!=OMX_ErrorNone){
770                 Log::getInstance()->log("Video", Log::DEBUG, "vid_dec Send Command to OMX State Idle %x", error);
771                 return 0;
772         }*/
773
774         OMX_VIDEO_PARAM_PORTFORMATTYPE ft_type;
775         memset(&ft_type,0,sizeof(ft_type));
776         ft_type.nSize=sizeof(ft_type);
777         ft_type.nVersion.nVersion=OMX_VERSION;
778
779         ft_type.nPortIndex=omx_codec_input_port;
780         if (h264) {
781                 ft_type.eCompressionFormat=OMX_VIDEO_CodingAVC;
782         } else {
783                 ft_type.eCompressionFormat=OMX_VIDEO_CodingMPEG2;
784         }
785
786         Demuxer* demux=Demuxer::getInstance();
787
788     ft_type.xFramerate=0;//25*(1<<16);//demux->getFrameRate()*(1<<16);
789     Log::getInstance()->log("Video", Log::DEBUG, "Framerate: %d",demux->getFrameRate());
790         error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamVideoPortFormat,&ft_type);
791         if (error!=OMX_ErrorNone){
792                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexParamVideoPortFormat failed %x", error);
793                 clock_mutex.Unlock();
794                 DeAllocateCodecsOMX();
795                 return 0;
796         }
797
798
799         if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) {
800                 Log::getInstance()->log("Video", Log::DEBUG, "vid_dec ChangeComponentState");
801                 clock_mutex.Unlock();
802                 DeAllocateCodecsOMX();
803                 return 0;
804         }
805
806
807         if (!PrepareInputBufsOMX()) {
808                 clock_mutex.Unlock();
809                 DeAllocateCodecsOMX();
810                 return 0;
811         }
812
813
814         error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,omx_vid_sched,omx_shed_input_port);
815         if (error!=OMX_ErrorNone){
816                 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel dec to sched failed %x", error);
817                 clock_mutex.Unlock();
818                 DeAllocateCodecsOMX();
819                 return 0;
820         }
821
822
823
824         if (!EnablePort(omx_vid_dec,omx_codec_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_input_port,false)
825                                                 ) {
826                 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX codec shed failed");
827                 clock_mutex.Unlock();
828                 DeAllocateCodecsOMX();
829                 return 0;
830         }
831
832         if ( !CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_output_port) || !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_input_port)) {
833                 clock_mutex.Unlock();
834                 DeAllocateCodecsOMX();
835                 return 0;
836         }
837
838         if (!ChangeComponentState(omx_vid_dec,OMX_StateExecuting)) {
839                 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_dec ChangeComponentState Execute");
840                 clock_mutex.Unlock();
841                 DeAllocateCodecsOMX();
842                 return 0;
843         }
844
845         error=OMX_SetupTunnel(omx_vid_sched,omx_shed_output_port,omx_vid_rend,omx_rend_input_port);
846         if (error!=OMX_ErrorNone){
847                 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel  sched to rend failed %x", error);
848                 clock_mutex.Unlock();
849                 DeAllocateCodecsOMX();
850                 return 0;
851         }
852
853         if (!EnablePort(omx_vid_sched,omx_shed_output_port,false) || !EnablePort(omx_vid_rend,omx_rend_input_port,false)
854                                                         ) {
855                 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX  shed rend failed");
856                 clock_mutex.Unlock();
857                 DeAllocateCodecsOMX();
858                 return 0;
859         }
860
861         if (!CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_output_port)
862                                         || !CommandFinished(omx_vid_rend,OMX_CommandPortEnable,omx_rend_input_port)) {
863                 clock_mutex.Unlock();
864                 DeAllocateCodecsOMX();
865                 return 0;
866         }
867
868         if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) {
869                 Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState");
870                 clock_mutex.Unlock();
871                 DeAllocateCodecsOMX();
872                 return 0;
873         }
874
875
876         if (!ChangeComponentState(omx_vid_sched,OMX_StateExecuting)) {
877                 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_sched ChangeComponentState Execute");
878                 clock_mutex.Unlock();
879                 DeAllocateCodecsOMX();
880                 return 0;
881         }
882
883         if (!ChangeComponentState(omx_vid_rend,OMX_StateExecuting)) {
884                 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_rend ChangeComponentState Execute");
885                 clock_mutex.Unlock();
886                 DeAllocateCodecsOMX();
887                 return 0;
888         }
889
890         //raspbi specifif
891         OMX_CONFIG_DISPLAYREGIONTYPE dispconf;
892         memset(&dispconf,0,sizeof(dispconf));
893         dispconf.nSize=sizeof(dispconf);
894         dispconf.nVersion.nVersion=OMX_VERSION;
895
896         dispconf.nPortIndex=omx_rend_input_port;
897
898         dispconf.set=OMX_DISPLAY_SET_LAYER ;
899         dispconf.layer=1;
900         error=OMX_SetConfig(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
901         if (error!=OMX_ErrorNone){
902                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
903                 clock_mutex.Unlock();
904                 DeAllocateCodecsOMX();
905                 return 0;
906         }
907
908 /*      dispconf.set=OMX_DISPLAY_SET_FULLSCREEN ;
909         dispconf.fullscreen=OMX_FALSE;
910         error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
911         if (error!=OMX_ErrorNone){
912                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
913                 clock_mutex.Unlock();
914                 DeAllocateCodecsOMX();
915                 return 0;
916         }
917
918         dispconf.set=OMX_DISPLAY_SET_DEST_RECT;
919         dispconf.dest_rect.x_offset=100;
920         dispconf.dest_rect.y_offset=100;
921         dispconf.dest_rect.width=640;
922         dispconf.dest_rect.height=480;
923         error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
924         if (error!=OMX_ErrorNone){
925                 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
926                 clock_mutex.Unlock();
927                 DeAllocateCodecsOMX();
928                 return 0;
929         }*/
930
931
932         playbacktimeoffset=-GetCurrentSystemTime();
933         paused=false;
934         iframemode=false;
935         omx_running=true;
936         clock_mutex.Unlock();
937         threadStart();
938
939         setClockExecutingandRunning();
940
941
942
943
944
945         return 1;
946 }
947
948 int VideoOMX::idleClock()
949 {
950         OMX_ERRORTYPE error;
951         OMX_STATETYPE temp_state;
952         clock_mutex.Lock();
953         OMX_GetState(omx_clock,&temp_state);
954
955         if (temp_state!=OMX_StateIdle) {
956                 if (!ChangeComponentState(omx_clock,OMX_StateIdle)) {
957                         Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Idle failed");
958                         clock_mutex.Unlock();
959                         return 0;
960                 }
961         }
962         clock_mutex.Unlock();
963         return 1;
964 }
965
966 int VideoOMX::setClockExecutingandRunning()
967 {
968         OMX_ERRORTYPE error;
969         OMX_STATETYPE temp_state;
970         clock_mutex.Lock();
971         OMX_GetState(omx_clock,&temp_state);
972
973         if (temp_state!=OMX_StateExecuting) {
974                 if (!ChangeComponentState(omx_clock,OMX_StateExecuting)) {
975                         Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Execute failed");
976                         clock_mutex.Unlock();
977                         DeAllocateCodecsOMX();
978                         return 0;
979                 }
980         }
981
982         OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
983         memset(&clock_conf,0,sizeof(clock_conf));
984         clock_conf.nSize=sizeof(clock_conf);
985         clock_conf.nVersion.nVersion=OMX_VERSION;
986         clock_conf.eState=OMX_TIME_ClockStateRunning;
987         error=OMX_SetConfig(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
988         if (error!=OMX_ErrorNone) {
989                 Log::getInstance()->log("Video", Log::DEBUG, "Clock IndexConfigTimeClockState failed %x", error);
990                 clock_mutex.Unlock();
991                 DeAllocateCodecsOMX();
992                 return 0;
993         }
994         clock_mutex.Unlock();
995         return 1;
996
997 }
998
999
1000 int VideoOMX::ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type) //needs to be called with locked mutex
1001 {
1002         OMX_ERRORTYPE error;
1003         error=OMX_SendCommand(handle,OMX_CommandStateSet,type,0);
1004         if (error!=OMX_ErrorNone){
1005                 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to OMX State %x %x",handle,type, error);
1006                 return 0;
1007         }
1008
1009         if (!CommandFinished(handle,OMX_CommandStateSet,type)) {
1010                 return 0;
1011         }
1012
1013         return 1;
1014 }
1015
1016
1017 int VideoOMX::EnablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait) //needs to be called with locked mutex
1018 {
1019         OMX_ERRORTYPE error;
1020         error=OMX_SendCommand(handle,OMX_CommandPortEnable,port,0);
1021         if (error!=OMX_ErrorNone){
1022                 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to enable port %x %x",handle,port, error);
1023                 return 0;
1024         }
1025
1026         if (!wait) return 1;
1027         if (!CommandFinished(handle,OMX_CommandPortEnable,port)) {
1028                 return 0;
1029         }
1030
1031         return 1;
1032 }
1033
1034
1035 int VideoOMX::DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait) //needs to be called with locked mutex
1036 {
1037         OMX_ERRORTYPE error;
1038         error=OMX_SendCommand(handle,OMX_CommandPortDisable,port,0);
1039         if (error!=OMX_ErrorNone){
1040                 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to disable port %x %x",handle,port, error);
1041                 return 0;
1042         }
1043
1044         if (!wait) return 1;
1045         if (!CommandFinished(handle,OMX_CommandPortDisable,port)) {
1046                 return 0;
1047         }
1048
1049
1050         return 1;
1051 }
1052
1053
1054
1055
1056 int VideoOMX::CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2) //needs to be called with locked mutex
1057 {
1058         int i=0;
1059         while (i<1000) {
1060                 omx_event_mutex.Lock();
1061                 list<VPE_OMX_EVENT>::iterator itty=omx_events.begin();
1062                 while (itty!=omx_events.end()) {
1063
1064                         VPE_OMX_EVENT current=*itty;
1065                         if (current.handle==handle) { //this is ours
1066                                 if (current.event_type==OMX_EventError) {
1067                                         omx_events.erase(itty);
1068                                         omx_event_mutex.Unlock();
1069                                         Log::getInstance()->log("Video", Log::DEBUG, "Command Finished on Error");
1070                                         return 0;
1071
1072                                 } else if (current.event_type==OMX_EventCmdComplete && current.data1==command && current.data2==data2) {
1073                                         omx_events.erase(itty);
1074                                         omx_event_mutex.Unlock();
1075                                         //Log::getInstance()->log("Video", Log::DEBUG, "Command Finished Completed");
1076                                         return 1;
1077                                 }
1078                         }
1079                         itty++;
1080
1081                 }
1082                 omx_event_mutex.Unlock();
1083                 MILLISLEEP(2);
1084                 i++;
1085
1086         }
1087         Log::getInstance()->log("Video", Log::DEBUG, "CommandFinished waited too long %x %x %x",handle,command, data2);
1088         return 0;
1089
1090 }
1091
1092
1093
1094
1095
1096 int VideoOMX::PrepareInputBufsOMX() //needs to be called with locked mutex
1097 {
1098         OMX_ERRORTYPE error;
1099         OMX_PARAM_PORTDEFINITIONTYPE port_def_type;
1100         memset(&port_def_type,0,sizeof(port_def_type));
1101         port_def_type.nSize=sizeof(port_def_type);
1102         port_def_type.nVersion.nVersion=OMX_VERSION;
1103         port_def_type.nPortIndex=omx_codec_input_port;
1104
1105         error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type);
1106
1107         if (error!=OMX_ErrorNone){
1108                         Log::getInstance()->log("Video", Log::DEBUG, "Get OMX OMX_IndexParamPortDefinition failed %x", error);
1109         }
1110 /*      Log::getInstance()->log("Video", Log::DEBUG, "Port para %d %d %d %d %d %d %d", port_def_type.nBufferCountActual,
1111                         port_def_type.nBufferCountMin,port_def_type.nBufferSize,port_def_type.bEnabled,port_def_type.bPopulated,
1112                         port_def_type.bBuffersContiguous,port_def_type.nBufferAlignment);*/
1113
1114         port_def_type.nBufferCountActual=100;
1115         port_def_type.nBufferSize=max(port_def_type.nBufferSize,200000); // for transcoder important
1116
1117         error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type);
1118
1119         if (error!=OMX_ErrorNone){
1120                         Log::getInstance()->log("Video", Log::DEBUG, "Set OMX OMX_IndexParamPortDefinition failed %x", error);
1121         }
1122
1123
1124         error=OMX_SendCommand(omx_vid_dec,OMX_CommandPortEnable,omx_codec_input_port,0);
1125         if (error!=OMX_ErrorNone){
1126                 Log::getInstance()->log("Video", Log::DEBUG, "Prepare Input bufs Send Command to enable port %x", error);
1127                 return 0;
1128         }
1129
1130         input_bufs_omx_mutex.Lock();
1131         for (unsigned int i=0; i< port_def_type.nBufferCountActual;i++) {
1132
1133         //      unsigned char* new_buffer_data=(unsigned char*)malloc(port_def_type.nbufferSize);
1134                 OMX_BUFFERHEADERTYPE *buf_head=NULL;
1135         /*      error=OMX_Usebuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nbufferSize,new_buffer_data);
1136                 if (error!=OMX_ErrorNone){
1137                         Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_Usebuffer failed %x", error);
1138                         input_bufs_omx_mutex.Unlock();
1139                         return 0;
1140                 }*/
1141                 error=OMX_AllocateBuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nBufferSize);
1142                 if (error!=OMX_ErrorNone){
1143                         Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_AllocateBuffer failed %x", error);
1144                                 input_bufs_omx_mutex.Unlock();
1145                         return 0;
1146                 }
1147                 input_bufs_omx_all.push_back(buf_head);
1148                 input_bufs_omx_free.push_back(buf_head);
1149         }
1150         omx_first_frame=true;
1151
1152         firstsynched=false;
1153         cur_input_buf_omx=NULL;
1154         input_bufs_omx_mutex.Unlock();
1155
1156
1157         Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark3");
1158         if (!CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_input_port)) {
1159                 return 0;
1160         }
1161         Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark4");
1162
1163         return 1;
1164 }
1165
1166 int VideoOMX::DestroyInputBufsOMX() //need s to be called with locked mutex
1167 {
1168         OMX_ERRORTYPE error;
1169
1170         cur_input_buf_omx=NULL;
1171         input_bufs_omx_mutex.Lock();
1172         for (int i=0; i< input_bufs_omx_all.size();i++) {
1173         //      free(input_bufs_omx_all[i]->pBuffer);
1174         //      input_bufs_omx_all[i]->pBuffer=NULL;
1175                 error=OMX_FreeBuffer(omx_vid_dec,omx_codec_input_port,input_bufs_omx_all[i]);
1176                 if (error!=OMX_ErrorNone){
1177                         Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_FreeBuffer failed %x", error);
1178                         input_bufs_omx_mutex.Unlock();
1179                         return 0;
1180                 }
1181
1182         }
1183         input_bufs_omx_all.clear();
1184         input_bufs_omx_free.clear();
1185         input_bufs_omx_present.clear();
1186         input_time_present.clear();
1187         input_bufs_omx_mutex.Unlock();
1188
1189 }
1190
1191
1192
1193
1194 int VideoOMX::DeAllocateCodecsOMX()
1195 {
1196         OMX_ERRORTYPE error;
1197         omx_running=false;
1198           Log::getInstance()->log("Video", Log::DEBUG, "enter deallocatecodecsomx");
1199         threadStop();
1200
1201
1202    if (cur_input_buf_omx) {
1203                 cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_EOS;
1204                 OMX_ERRORTYPE error=ProtOMXEmptyThisBuffer(omx_vid_dec,cur_input_buf_omx);
1205                 if (error!=OMX_ErrorNone) {
1206                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error);
1207                 }
1208
1209                 cur_input_buf_omx=NULL;//write out old data
1210         }
1211    clock_mutex.Lock();
1212         if (omx_vid_dec) {
1213                 // first stop the omx elements
1214                 if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) {
1215                         Log::getInstance()->log("Video", Log::DEBUG, "vid_dec ChangeComponentState");
1216
1217                 }
1218                 clock_mutex.Unlock();
1219
1220                 idleClock();
1221                 clock_mutex.Lock();
1222
1223
1224                 if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) {
1225                         Log::getInstance()->log("Video", Log::DEBUG, "vid_shed ChangeComponentState");
1226
1227                 }
1228
1229                 if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) {
1230                         Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState");
1231
1232                 }
1233
1234
1235
1236         // TODO proper deinit sequence
1237                 // first flush all buffers
1238
1239
1240                 error = OMX_SendCommand(omx_vid_dec, OMX_CommandFlush,
1241                                 omx_codec_output_port, NULL);
1242                 if (error != OMX_ErrorNone) {
1243                         Log::getInstance()->log("Video", Log::DEBUG,
1244                                         "OMX_Flush codec out failed %x", error);
1245
1246                 }
1247
1248                 error = OMX_SendCommand(omx_vid_sched, OMX_CommandFlush,
1249                                 omx_shed_input_port, NULL);
1250                 if (error != OMX_ErrorNone) {
1251                         Log::getInstance()->log("Video", Log::DEBUG,
1252                                         "OMX_Flush shed in failed %x", error);
1253
1254                 }
1255
1256                 if (!CommandFinished(omx_vid_dec, OMX_CommandFlush,
1257                                 omx_codec_output_port)) {
1258                         Log::getInstance()->log("Video", Log::DEBUG,
1259                                         "flush cmd codec  failed");
1260                 }
1261
1262                 if (!CommandFinished(omx_vid_sched, OMX_CommandFlush,
1263                                 omx_shed_input_port)) {
1264                         Log::getInstance()->log("Video", Log::DEBUG,
1265                                         "flush cmd  shed failed");
1266                 }
1267
1268
1269
1270
1271                 error = OMX_SendCommand(omx_vid_rend, OMX_CommandFlush,
1272                                 omx_rend_input_port, NULL);
1273                 if (error != OMX_ErrorNone) {
1274                         Log::getInstance()->log("Video", Log::DEBUG,
1275                                         "OMX_Flush rend in failed %x", error);
1276
1277                 }
1278
1279                 error = OMX_SendCommand(omx_vid_sched, OMX_CommandFlush,
1280                                 omx_shed_output_port, NULL);
1281                 if (error != OMX_ErrorNone) {
1282                         Log::getInstance()->log("Video", Log::DEBUG,
1283                                         "OMX_Flush shed out failed %x", error);
1284
1285                 }
1286
1287
1288
1289                 if (!CommandFinished(omx_vid_rend, OMX_CommandFlush,
1290                                 omx_rend_input_port)) {
1291                         Log::getInstance()->log("Video", Log::DEBUG,
1292                                         "flush cmd shed rend failed");
1293                 }
1294
1295                 if (!CommandFinished(omx_vid_sched, OMX_CommandFlush,
1296                                 omx_shed_output_port)) {
1297                         Log::getInstance()->log("Video", Log::DEBUG,
1298                                         "flush cmd shed rend failed");
1299                 }
1300
1301
1302
1303
1304
1305                 error=OMX_SendCommand(omx_clock,OMX_CommandFlush, omx_clock_output_port, NULL);
1306                 if (error!=OMX_ErrorNone){
1307                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush clock out failed %x", error);
1308
1309                 }
1310
1311                 error=OMX_SendCommand(omx_vid_sched,OMX_CommandFlush, omx_shed_clock_port, NULL);
1312                 if (error!=OMX_ErrorNone){
1313                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush shed clock failed %x", error);
1314
1315                 }
1316
1317                 if (!CommandFinished(omx_clock,OMX_CommandFlush,omx_clock_output_port) ||
1318                         !CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_clock_port)) {
1319                                 Log::getInstance()->log("Video", Log::DEBUG, "flush cmd clock shed failed");
1320                 }
1321
1322
1323
1324
1325                 error = OMX_SendCommand(omx_vid_dec, OMX_CommandFlush,
1326                                 omx_codec_input_port, NULL);
1327                 if (error != OMX_ErrorNone) {
1328                         Log::getInstance()->log("Video", Log::DEBUG,
1329                                         "OMX_Flush codec out failed %x", error);
1330
1331                 }
1332
1333
1334
1335
1336                 DestroyInputBufsOMX();
1337
1338                 //todo flushing
1339                 if (!DisablePort(omx_vid_sched,omx_shed_output_port,true)) {
1340                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 2 ");
1341                 }
1342                 if (!DisablePort(omx_vid_rend,omx_rend_input_port,true)) {
1343                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 1");
1344                 }
1345
1346
1347
1348
1349                 if (!DisablePort(omx_vid_dec,omx_codec_output_port,true)) {
1350                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 6");
1351                 }
1352
1353
1354
1355                 if (!DisablePort(omx_vid_dec,omx_codec_input_port,true)) {
1356                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 7");
1357                 }
1358
1359
1360
1361
1362                 if (!DisablePort(omx_vid_sched,omx_shed_input_port,true)) {
1363                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 3");
1364                 }
1365
1366                 if (!DisablePort(omx_vid_sched,omx_shed_clock_port,true)) {
1367                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 4");
1368                 }
1369
1370                 if (!DisablePort(omx_clock,omx_clock_output_port,true)) {
1371                         Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 5");
1372                 }
1373
1374
1375
1376
1377                 error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,NULL,NULL);
1378                 if (error!=OMX_ErrorNone) {
1379                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1380
1381                 }
1382
1383                 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_input_port,NULL,NULL);
1384                 if (error!=OMX_ErrorNone) {
1385                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1386
1387                 }
1388
1389
1390                 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_output_port,NULL,NULL);
1391                 if (error!=OMX_ErrorNone) {
1392                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1393
1394                 }
1395
1396                 error=OMX_SetupTunnel(omx_vid_rend,omx_rend_input_port,NULL,NULL);
1397                 if (error!=OMX_ErrorNone) {
1398                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1399
1400                 }
1401
1402
1403                 error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,NULL,NULL);
1404                 if (error!=OMX_ErrorNone) {
1405                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1406
1407                 }
1408
1409                 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_clock_port,NULL,NULL);
1410                 if (error!=OMX_ErrorNone) {
1411                         Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1412
1413                 }
1414
1415
1416
1417
1418                 error=OMX_FreeHandle(omx_vid_dec);
1419                 error=OMX_FreeHandle(omx_vid_sched);
1420                 error=OMX_FreeHandle(omx_vid_rend);
1421                 omx_vid_dec=NULL;
1422                 clock_mutex.Unlock();
1423                 destroyClock();
1424                 if (error!=OMX_ErrorNone) {
1425                         Log::getInstance()->log("Video", Log::DEBUG, "FreeHandle failed %d", error);
1426                 }
1427         } else  clock_mutex.Unlock();
1428           Log::getInstance()->log("Video", Log::DEBUG, "leave deallocate codecs OMX");
1429
1430         return 1;
1431 }
1432
1433
1434 void VideoOMX::destroyClock()
1435 {
1436         clock_mutex.Lock();
1437         if (clock_references>0) {
1438                 clock_references--;
1439                 if (clock_references==0) {
1440                         OMX_ERRORTYPE error;
1441                         Log::getInstance()->log("Video", Log::DEBUG, "destroy omx clock");
1442                         error=OMX_FreeHandle(omx_clock);
1443                         if (error!=OMX_ErrorNone) {
1444                                 Log::getInstance()->log("Video", Log::DEBUG, "FreeHandle failed %d", error);
1445                         }
1446
1447                 }
1448         }
1449         clock_mutex.Unlock();
1450
1451 }
1452
1453 int VideoOMX::stop()
1454 {
1455   if (!initted) return 0;
1456   iframemode=false;
1457
1458   //Check if libav mode
1459   DeAllocateCodecsOMX();
1460
1461
1462
1463
1464 //  if (ioctl(fdVideo, AV_SET_VID_STOP, 0) != 0) return 0;
1465   return 1;
1466 }
1467
1468 int VideoOMX::reset()
1469 {
1470   if (!initted) return 0;
1471
1472   iframemode=false;
1473   DeAllocateCodecsOMX();
1474 //  if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0;
1475   return 1;
1476 }
1477
1478 int VideoOMX::pause()
1479 {
1480   if (!initted) return 0;
1481   Log::getInstance()->log("Video", Log::DEBUG, "enter pause");
1482   if (!paused) {
1483           paused=true;
1484           //maybe also change omx clock?
1485           pausetimecode=GetCurrentSystemTime();
1486
1487   }
1488   return 1;
1489 }
1490
1491 int VideoOMX::unPause() // FIXME get rid - same as play!! Not here!
1492 {
1493   if (!initted) return 0;
1494   Log::getInstance()->log("Video", Log::DEBUG, "enter unpause");
1495
1496   if (paused) {
1497           playbacktimeoffset+=GetCurrentSystemTime()-pausetimecode;
1498           paused=false; // may be also change omx clock
1499   }
1500
1501   return 1;
1502 }
1503
1504 int VideoOMX::fastForward()
1505 {
1506   if (!initted) return 0;
1507
1508 //  if (ioctl(fdVideo, AV_SET_VID_libavWD, 1) != 0) return 0;
1509   return 1;
1510 }
1511
1512 int VideoOMX::unFastForward()
1513 {
1514   if (!initted) return 0;
1515
1516 //  if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; // don't need this.
1517
1518  //// if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
1519   return 1;
1520 }
1521
1522 int VideoOMX::attachFrameBuffer()
1523 {
1524   if (!initted) return 0;
1525
1526 //  if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
1527   return 1;
1528 }
1529
1530 int VideoOMX::blank(void)
1531 {
1532 //  if (ioctl(fdVideo, AV_SET_VID_FB, 1) != 0) return 0;
1533 //  if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
1534   return 1;
1535 }
1536
1537 ULLONG VideoOMX::getCurrentTimestamp()
1538 {
1539   if (iframemode) return 0;
1540   return lastreftimePTS;
1541 }
1542
1543 // to be removed
1544 /*
1545 ULONG VideoOMX::timecodeToFrameNumber(ULLONG timecode)
1546 {
1547   if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
1548   else               return (ULONG)(((double)timecode / (double)90000) * (double)30);
1549 }
1550
1551 */
1552 #ifdef DEV
1553 int VideoOMX::test()
1554 {
1555   return 0;
1556
1557 //  ULLONG stc = 0;
1558 //  return ioctl(fdVideo, AV_SET_VID_STC, &stc);
1559 /*
1560  // reset();
1561   return 1;
1562 */
1563 }
1564
1565 int VideoOMX::test2()
1566 {
1567   return 0;
1568 }
1569 #endif
1570
1571
1572
1573 long long VideoOMX::SetStartOffset(long long curreftime, bool *rsync)
1574 {
1575   *rsync=false;
1576   if (offsetnotset) {
1577     startoffset=curreftime;//offset is set for audio
1578     offsetnotset=false;
1579     offsetvideonotset=false;
1580   } else {
1581     if (offsetvideonotset) {
1582       offsetvideonotset=false;
1583       *rsync=true;
1584     } else {
1585       if ( (curreftime-lastrefvideotime)>10000000LL
1586         || (curreftime-lastrefvideotime)<-10000000LL) {//if pts jumps to big resync
1587         startoffset+=curreftime-lastrefvideotime;
1588         lastrefaudiotime+=curreftime-lastrefvideotime;
1589         //*rsync=true;
1590         offsetaudionotset=true;
1591
1592       }
1593     }
1594
1595   }
1596
1597   lastrefvideotime=curreftime;
1598
1599   return startoffset;
1600
1601 }
1602
1603 long long VideoOMX::SetStartAudioOffset(long long curreftime, bool *rsync)
1604 {
1605   *rsync=false;
1606   if (offsetnotset) {
1607     startoffset=curreftime;
1608     offsetnotset=false;
1609     offsetaudionotset=false;
1610   }else {
1611     if (offsetaudionotset) {
1612       offsetaudionotset=false;
1613       *rsync=true;
1614     } else {
1615       if ( (curreftime-lastrefaudiotime)>10000000LL
1616         || (curreftime-lastrefaudiotime)<-10000000LL) {//if pts jumps to big resync
1617         startoffset+=curreftime-lastrefaudiotime;
1618         lastrefvideotime+=curreftime-lastrefaudiotime;
1619         //*rsync=true;
1620         offsetvideonotset=true;
1621
1622       }
1623     }
1624
1625   }
1626   lastrefaudiotime=curreftime;
1627   return startoffset;
1628
1629 }
1630
1631 void VideoOMX::ResetTimeOffsets() {
1632   offsetnotset=true; //called from demuxer
1633   offsetvideonotset=true;
1634   offsetaudionotset=true;
1635   startoffset=0;
1636   lastrefaudiotime=0;
1637   lastrefvideotime=0;
1638   lastreftimeOMX=0;
1639   lastreftimePTS=0;
1640 }
1641
1642 long long VideoOMX::GetCurrentSystemTime()
1643 {
1644         struct timespec ts;
1645         clock_gettime(CLOCK_MONOTONIC, &ts);
1646         return ts.tv_sec*10000000LL+ts.tv_nsec/100LL;
1647 }
1648
1649 void VideoOMX::WaitUntil(long long time)
1650 {
1651         struct timespec interval;
1652         interval.tv_sec=time/10000000LL;
1653         interval.tv_nsec=(time %10000000LL)*100LL;
1654         while (clock_nanosleep(CLOCK_MONOTONIC,TIMER_ABSTIME,&interval,NULL)==EINTR) {
1655                 //Log::getInstance()->log("Video", Log::DEBUG, "Wait until multi");
1656
1657         };
1658 }
1659
1660 bool VideoOMX::FrameSkip(long long pts)
1661 {
1662         //ok first calculate the absolute time
1663         bool skip=false;
1664         long long target_time=pts-playbacktimeoffset;
1665         // we have to wait untile the next frame
1666         long long offset=Demuxer::getInstance()->getFrameRate();
1667         if (offset==0) offset=25;
1668         offset=10000000LL/offset;
1669         target_time+=offset;
1670         long long current_time=GetCurrentSystemTime();
1671         if (!skipping) {
1672                 if ((target_time-current_time)<-1000000LL) {
1673                         skip=true; // we are too slow
1674                         skipping=true;
1675                 /*      Log::getInstance()->log("Video", Log::DEBUG,
1676                                                                                                                 "Skipping frames1 %lld %lld",target_time-current_time,pts);
1677                         Log::getInstance()->log("Video", Log::DEBUG, "skip detail pts: %lld target: %lld sys: %lld off: %lld diff %lld",pts,target_time,current_time,offset,
1678                                                 target_time-current_time);*/
1679                 }  else {
1680                         skipping=false;
1681                 }
1682         } else {
1683                 if ((target_time - current_time) < 0LL) {
1684                         skip = true; // we are too slow
1685                         skipping = true;
1686                 /*      Log::getInstance()->log("Video", Log::DEBUG,"Skipping frames2 %lld %lld",target_time-current_time,pts);
1687                         Log::getInstance()->log("Video", Log::DEBUG, "skip detail pts: %lld target: %lld sys: %lld off: %lld diff %lld",pts,target_time,current_time,offset,
1688                                                                         target_time-current_time);*/
1689                 } else {
1690                         skipping = false;
1691                 }
1692
1693         }
1694
1695         return skip;
1696 }
1697
1698 void VideoOMX::FrameWaitforDisplay(long long pts)
1699 {
1700         //ok first calculate the absolute time
1701         long long target_time=pts-playbacktimeoffset;
1702         // we have to wait untile the next frame
1703         long long offset=Demuxer::getInstance()->getFrameRate();
1704         long long current_time=GetCurrentSystemTime();
1705         if (offset==0) offset=25;
1706         offset=10000000LL/offset;
1707         target_time+=offset;
1708         if ((target_time-current_time)>1000000LL) target_time=current_time+1000000LL; // something is wrong do not wait too long
1709         //Log::getInstance()->log("Video", Log::DEBUG, "Wait for display pts: %lld target: %lld sys: %lld off: %lld diff %lld",pts,target_time,current_time,offset,
1710         //              target_time-current_time);
1711
1712         WaitUntil(target_time);
1713         //Log::getInstance()->log("Video", Log::DEBUG, "Wait for display out %lld",GetCurrentSystemTime());
1714 }
1715
1716 void VideoOMX::AdjustAudioPTS(long long pts)
1717 {
1718         long long newplaybacktimeoffset=pts-GetCurrentSystemTime();
1719 /*      if ((newplaybacktimeoffset-1000000LL)>playbacktimeoffset
1720             || (newplaybacktimeoffset+1000000LL)<playbacktimeoffset) {
1721                 Log::getInstance()->log("Video", Log::DEBUG, "Adjust Playbackoffsettime o: %lld n: %lld",
1722                                 playbacktimeoffset,newplaybacktimeoffset);*/
1723                 playbacktimeoffset=newplaybacktimeoffset;
1724
1725         //}
1726 }
1727
1728 void VideoOMX::threadPostStopCleanup()
1729 {
1730         //Doing nothing
1731         //goo;
1732         Log::getInstance()->log("Video", Log::DEBUG,
1733                                                                                                 "end thread");
1734 }
1735
1736
1737 void VideoOMX::threadMethod()
1738 {
1739         Log::getInstance()->log("Video", Log::DEBUG,
1740                                                                                 "start thread");
1741         while (true) {
1742
1743                 OMX_BUFFERHEADERTYPE* pict=NULL;
1744                 long long time;
1745                 if (!paused) {
1746                         input_bufs_omx_mutex.Lock();
1747                         if (input_bufs_omx_present.size()>0) {
1748
1749                                 pict=input_bufs_omx_present.front();
1750                                 time=input_time_present.front();
1751                                 input_bufs_omx_present.pop_front();
1752                                 input_time_present.pop_front();
1753                         }
1754                         input_bufs_omx_mutex.Unlock();
1755                 }
1756
1757                 if ( pict) {
1758                         //Log::getInstance()->log("Video", Log::DEBUG,
1759                         //                                                                                      "Got pict");
1760                         if (time!=0 &&FrameSkip(time) && !(pict->nFlags &OMX_BUFFERFLAG_STARTTIME)) {
1761
1762                                 input_bufs_omx_mutex.Lock();
1763                                 input_bufs_omx_free.push_back(pict);
1764                                 input_bufs_omx_mutex.Unlock();
1765
1766                         } else {
1767                                 OMX_ERRORTYPE error = ProtOMXEmptyThisBuffer(omx_vid_dec, pict);
1768                                 if (error != OMX_ErrorNone) {
1769                                         Log::getInstance()->log("Video", Log::DEBUG,
1770                                                         "OMX_EmptyThisBuffer failed %x", error);
1771                                 }
1772                                 if (time!=0) FrameWaitforDisplay(time);
1773                         }
1774                 } else {
1775                         MILLISLEEP(5);
1776                 }
1777
1778                 threadCheckExit();
1779         }
1780         Log::getInstance()->log("Video", Log::DEBUG,
1781                                                                                         "end thread");
1782 }
1783
1784 void VideoOMX::PutBufferToPres(OMX_BUFFERHEADERTYPE* buffer, long long time)
1785 {
1786         input_bufs_omx_mutex.Lock();
1787         input_bufs_omx_present.push_back(buffer);
1788         input_time_present.push_back(time);
1789         input_bufs_omx_mutex.Unlock();
1790
1791 }
1792
1793 OMX_ERRORTYPE VideoOMX::ProtOMXEmptyThisBuffer(OMX_HANDLETYPE handle, OMX_BUFFERHEADERTYPE* buffer)
1794 {
1795         // protect the call to empty this buffer
1796         int oldcancelstate;
1797         int oldcanceltype;
1798         pthread_testcancel();
1799         pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldcancelstate);
1800         pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldcanceltype);
1801         clock_mutex.Lock();
1802         OMX_ERRORTYPE ret_val;
1803         ret_val=OMX_EmptyThisBuffer(handle,buffer);
1804         clock_mutex.Unlock();
1805         pthread_setcancelstate(oldcancelstate, NULL);
1806         pthread_setcanceltype(oldcanceltype, NULL);
1807         pthread_testcancel();
1808         return ret_val;
1809 }
1810
1811 void VideoOMX::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
1812 {
1813   mediapacket = mplist.front();
1814 }
1815
1816 UINT VideoOMX::DeliverMediaSample(UCHAR* buffer, UINT *samplepos)
1817 {
1818   DeliverMediaPacket(mediapacket, buffer, samplepos);
1819   if (*samplepos == mediapacket.length) {
1820     *samplepos = 0;
1821     return 1;
1822   }
1823   else return 0;
1824 }
1825
1826 UINT VideoOMX::DeliverMediaPacket(MediaPacket packet,
1827                 const UCHAR* buffer,
1828                 UINT *samplepos)
1829 {
1830         if (packet.type == MPTYPE_VIDEO_H264)
1831         {
1832                 h264=true;
1833         }
1834         else
1835         {
1836                 h264=false;
1837         }
1838
1839
1840         //Later add fail back code for libav
1841 /*      if (!videoon) {
1842                 *samplepos+=packet.length;
1843                 return packet.length;
1844         }*/
1845
1846
1847         if (!omx_running) return 0; // if we are not runnig do not do this
1848         if (paused) return 0; //Block if we pause
1849
1850         long long current_media_time=GetCurrentSystemTime()+playbacktimeoffset;
1851 /*      if (packet.synched &&
1852                         (packet.presentation_time<0 /*|| // preroll skip frames
1853                         (packet.presentation_time+5000000LL)<(current_media_time)*)) { // we are late skip
1854                 Log::getInstance()->log("Video", Log::DEBUG, "DeliverMediaPacketOMX Preroll or too late %lld %lld; %lld", packet.presentation_time,current_media_time,playbacktimeoffset);
1855                 *samplepos=packet.length;
1856                 return packet.length;
1857         }*/
1858
1859         OMX_ERRORTYPE error;
1860
1861         /*First Check, if we have an video sample*/
1862         if (iframemode) {
1863                 //samplepos=0;
1864                 MILLISLEEP(10);
1865                 return 0; //Not in iframe mode!
1866         }
1867
1868         UINT headerstrip=0;
1869         if (packet.disconti) {
1870                 firstsynched=false;
1871                 if (cur_input_buf_omx) {
1872                         PutBufferToPres(cur_input_buf_omx, lastreftimeOMX);
1873                         cur_input_buf_omx=NULL;
1874                 }
1875         }
1876
1877         /*Inspect PES-Header */
1878
1879 //      OMX_STATETYPE temp_state;
1880 //      OMX_GetState(omx_vid_dec,&temp_state);
1881
1882         if (*samplepos==0) {//stripheader
1883                 headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
1884         //      if (h264) Log::getInstance()->log("Video", Log::DEBUG, "PES info %x %x %x %x",
1885         //                      buffer[packet.pos_buffer+0],buffer[packet.pos_buffer+1],buffer[packet.pos_buffer+2],buffer[packet.pos_buffer+3]);
1886                 *samplepos+=headerstrip;
1887                 if ( packet.synched ) {
1888                         if (cur_input_buf_omx) {
1889                                 cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_ENDOFFRAME;
1890                                 PutBufferToPres(cur_input_buf_omx, lastreftimeOMX);
1891                                 cur_input_buf_omx=NULL;//write out old data
1892
1893
1894                         }
1895                         firstsynched=true;
1896                 } else {
1897                         if (!firstsynched) {//
1898                                 *samplepos=packet.length;//if we have not processed at least one
1899                                 return packet.length;//synched packet ignore it!
1900                         }
1901                 }
1902         }
1903
1904         if (!cur_input_buf_omx) {
1905                 input_bufs_omx_mutex.Lock();
1906                 if (input_bufs_omx_free.size()==0) {
1907                         input_bufs_omx_mutex.Unlock();
1908                         //Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket no free sample");
1909                         return 0; // we do not have a free media sample
1910
1911                 }
1912                 cur_input_buf_omx=input_bufs_omx_free.front();
1913                 cur_input_buf_omx->nFilledLen=0;
1914                 cur_input_buf_omx->nOffset=0;
1915                 cur_input_buf_omx->nTimeStamp=0;
1916                 input_bufs_omx_free.pop_front();
1917                 input_bufs_omx_mutex.Unlock();
1918         }
1919
1920
1921
1922
1923         if (cur_input_buf_omx->nFilledLen==0) {//will only be changed on first packet
1924                 if (packet.synched) {
1925                 //      Log::getInstance()->log("Video", Log::DEBUG, "packet synched marker");
1926
1927                         //lastreftimePTS=packet.pts;
1928                    if (omx_first_frame) { // TODO time
1929                            cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_STARTTIME;
1930                            Log::getInstance()->log("Video", Log::DEBUG, "Starttime");
1931                            omx_first_frame=false;
1932                    } else {
1933                            //cur_input_buf_omx->nFlags=0;
1934                            cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_TIME_UNKNOWN;
1935                    }
1936                    lastreftimeOMX=packet.presentation_time;
1937                  //  Log::getInstance()->log("Video", Log::DEBUG, "Time code %lld pts %lld", lastreftimeOMX,packet.pts);
1938                    lastreftimePTS=packet.pts;
1939                    cur_input_buf_omx->nTimeStamp=0;//lastreftimeOMX; // the clock component is faulty;
1940                 }
1941                 else
1942                 {
1943                         cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
1944                         cur_input_buf_omx->nTimeStamp=0;
1945
1946
1947                         //  ms->SetSyncPoint(TRUE);
1948                 }
1949                 if (packet.disconti) cur_input_buf_omx->nFlags|=OMX_BUFFERFLAG_DISCONTINUITY;
1950
1951
1952
1953         }
1954         unsigned int haveToCopy=packet.length-*samplepos;
1955
1956         while (haveToCopy> (cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen)) {
1957                 unsigned int cancopy=cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen;
1958                 memcpy(cur_input_buf_omx->pBuffer+cur_input_buf_omx->nFilledLen,buffer+packet.pos_buffer+*samplepos,cancopy);
1959                 haveToCopy-=cancopy;
1960                 cur_input_buf_omx->nFilledLen+=cancopy;
1961                 *samplepos+=cancopy;
1962                 // push old buffer out
1963
1964                 PutBufferToPres(cur_input_buf_omx, 0LL);
1965                 // get5 new buffer
1966                 input_bufs_omx_mutex.Lock();
1967                 if (input_bufs_omx_free.size()==0) {
1968                         input_bufs_omx_mutex.Unlock();
1969                         //Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket no free sample");
1970                         return *samplepos; // we do not have a free media sample
1971                 }
1972                 cur_input_buf_omx=input_bufs_omx_free.front();
1973                 cur_input_buf_omx->nFilledLen=0;
1974                 cur_input_buf_omx->nOffset=0;
1975                 cur_input_buf_omx->nTimeStamp=0;
1976                 input_bufs_omx_free.pop_front();
1977                 input_bufs_omx_mutex.Unlock();
1978
1979                 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
1980
1981         }
1982         memcpy(cur_input_buf_omx->pBuffer+cur_input_buf_omx->nFilledLen,
1983                         buffer+packet.pos_buffer+*samplepos,haveToCopy);
1984         cur_input_buf_omx->nFilledLen+=haveToCopy;
1985
1986
1987
1988         *samplepos+=haveToCopy;
1989
1990         return *samplepos;
1991
1992 }
1993
1994
1995
1996
1997 bool VideoOMX::displayIFrame(const UCHAR* buffer, UINT length) {
1998         if (!omx_running) return false;
1999         if (!iframemode)
2000                 EnterIframePlayback();
2001
2002         int haveToCopy = length;
2003
2004         if (!cur_input_buf_omx) {
2005                 input_bufs_omx_mutex.Lock();
2006                 if (input_bufs_omx_free.size() == 0) {
2007                         input_bufs_omx_mutex.Unlock();
2008                 //      Log::getInstance()->log("Video", Log::DEBUG,
2009                         //              "Deliver MediaPacket no free sample");
2010                         return false; // we do not have a free media sample
2011
2012                 }
2013                 cur_input_buf_omx = input_bufs_omx_free.front();
2014                 cur_input_buf_omx->nFilledLen = 0;
2015                 cur_input_buf_omx->nOffset = 0;
2016                 cur_input_buf_omx->nTimeStamp = 0;
2017                 input_bufs_omx_free.pop_front();
2018                 input_bufs_omx_mutex.Unlock();
2019         }
2020
2021         int read_pos = 0;
2022         unsigned int pattern, packet_length;
2023         unsigned int headerstrip = 0;
2024         bool first = true;
2025         if (length < 4){
2026                 return false;
2027         }
2028         //Now we strip the pes header
2029         pattern = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]);
2030         while (read_pos + 7 <= length) {
2031                 pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos + 3];
2032                 if (pattern < 0x000001E0 || pattern > 0x000001EF) {
2033                         read_pos++;
2034                         continue;
2035                 } else {
2036                         headerstrip = buffer[read_pos + 8] + 9/*is this right*/;
2037                         packet_length = ((buffer[read_pos + 4] << 8)
2038                                         | (buffer[read_pos + 5])) + 6;
2039                         if (read_pos + packet_length > length)
2040                                 read_pos = length;
2041                         else {
2042                                 if ((headerstrip < packet_length)
2043                                                 && (cur_input_buf_omx->nFilledLen + packet_length
2044                                                                 - headerstrip) > cur_input_buf_omx->nAllocLen) {
2045                                         if (first) {
2046                                                 cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_STARTTIME;
2047
2048                                         } else {
2049                                                 cur_input_buf_omx->nFlags
2050                                                                 |= OMX_BUFFERFLAG_TIME_UNKNOWN;
2051
2052                                         }
2053                                         cur_input_buf_omx->nTimeStamp = 0;
2054                                         PutBufferToPres(cur_input_buf_omx, 0);
2055                                         cur_input_buf_omx = NULL;
2056
2057                                         if (!cur_input_buf_omx) {
2058                                                 int count = 0;
2059                                                 while (count < 100 && omx_running && iframemode) {
2060                                                         count++;
2061
2062                                                         input_bufs_omx_mutex.Lock();
2063                                                         if (input_bufs_omx_free.size() == 0) {
2064                                                                 input_bufs_omx_mutex.Unlock();
2065                                         //                      Log::getInstance()->log("Video", Log::DEBUG,
2066                                                 //                              "Ifrane no free sample");
2067                                                                 MILLISLEEP(5);
2068                                                                 if (!omx_running) return false;
2069                                                                 continue;
2070                                                         }
2071                                                         cur_input_buf_omx = input_bufs_omx_free.front();
2072                                                         cur_input_buf_omx->nFilledLen = 0;
2073                                                         cur_input_buf_omx->nOffset = 0;
2074                                                         cur_input_buf_omx->nTimeStamp = 0;
2075                                                         input_bufs_omx_free.pop_front();
2076                                                         input_bufs_omx_mutex.Unlock();
2077                                                         break;
2078                                                 }
2079                                                 if (!cur_input_buf_omx)
2080                                                         return false;
2081                                         }
2082
2083                                 }
2084                                 if (packet_length > headerstrip) {
2085                                         memcpy(
2086                                                         cur_input_buf_omx->pBuffer
2087                                                                         + cur_input_buf_omx->nFilledLen,
2088                                                         buffer + read_pos + headerstrip,
2089                                                         packet_length - headerstrip);
2090                                         cur_input_buf_omx->nFilledLen += packet_length
2091                                                         - headerstrip;
2092                                 }
2093                                 read_pos += packet_length;
2094
2095                                 pattern = (buffer[read_pos] << 16)
2096                                                 | (buffer[read_pos + 1] << 8) | (buffer[read_pos + 2]);
2097                         }
2098                 }
2099         }
2100
2101         if (first) {
2102                 cur_input_buf_omx->nFlags = OMX_BUFFERFLAG_STARTTIME;
2103
2104         } else {
2105                 cur_input_buf_omx->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
2106
2107         }
2108         cur_input_buf_omx->nTimeStamp = 0;
2109         PutBufferToPres(cur_input_buf_omx, 0);
2110         cur_input_buf_omx = NULL;
2111
2112
2113         MILLISLEEP(40); //Block a bit
2114         return true;
2115 }
2116
2117 int VideoOMX::EnterIframePlayback()
2118 {
2119         clock_mutex.Lock();
2120         if (cur_input_buf_omx) {
2121                 PutBufferToPres(cur_input_buf_omx, lastreftimeOMX);
2122
2123                 cur_input_buf_omx = NULL;
2124         }
2125         clock_mutex.Unlock();
2126         iframemode=true;
2127
2128         return 1;
2129 }
2130