]> git.vomp.tv Git - vompclient.git/blob - imageomx.cc
Fix VRecording showing graphic at bottom left when it shouldn't
[vompclient.git] / imageomx.cc
1 /*
2     Copyright 2004-2005 Chris Tallon, 2009,2014 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, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include <bcm_host.h>
21
22 #include "log.h"
23 #include "videoomx.h"
24 #include "vdr.h"
25 #include "woptionpane.h"
26 #include "util.h"
27 #include "osdopenvg.h"
28
29 #include "imageomx.h"
30
31 static const char* TAG = "ImageOMX";
32
33 ImageOMX::ImageOMX(OsdVector::PictureReader * treader):OsdVector::PictureDecoder(treader)
34 {
35   initted = 0;
36
37   omx_running=false;
38   pictInfValid=false;
39   omx_imag_decode/*dec*/=NULL;
40   omx_egl_render/*dec*/=NULL;
41
42   buf_head_egl=NULL;
43   curformat = Unsupported;
44
45   strcpy(L_VPE_OMX_IMAGE_DECODER, VPE_OMX_IMAGE_DECODER);
46   strcpy(L_VPE_OMX_EGL_REND, VPE_OMX_EGL_REND);
47 }
48
49 ImageOMX::~ImageOMX()
50 {
51
52 }
53
54 void ImageOMX::init()
55 {
56  // AllocateCodecsOMX();
57 }
58
59 void ImageOMX::shutdown()
60 {
61         LogNT::getInstance()->debug(TAG, "shutdown");
62         //DeAllocateCodecsOMX();
63 }
64
65
66
67
68
69 OMX_ERRORTYPE ImageOMX::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE /*hcomp*/,OMX_IN OMX_PTR /*appdata*/,OMX_IN OMX_BUFFERHEADERTYPE* buffer){
70
71         //LogNT::getInstance()->info(TAG, "EmptyBufferDone");
72         ImageOMX* image = static_cast<ImageOMX*>(buffer->pAppPrivate);
73         image->ReturnEmptyOMXBuffer(buffer);
74         return OMX_ErrorNone;
75
76 }
77
78 void ImageOMX::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){
79         input_bufs_omx_mutex.lock();
80         /*if (buffer->pBuffer) {
81                 free(buffer->pBuffer);
82                 buffer->pBuffer = NULL;
83         }*/
84         buffer->nAllocLen= 0;
85         //LogNT::getInstance()->info(TAG, "ReturnEmptyOMXBuffer {}",input_bufs_omx_free.size());
86         input_bufs_omx_free.push_back(buffer);
87         //LogNT::getInstance()->info(TAG, "ReturnEmptyOMXBuffer {}",input_bufs_omx_free.size());
88         input_bufs_omx_mutex.unlock();
89         VideoOMX* video = static_cast<VideoOMX*>(Video::getInstance());
90
91         video->signalOmx();
92 }
93
94 OMX_ERRORTYPE ImageOMX::FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE /*hcomp*/, OMX_IN OMX_PTR /*appdata*/,OMX_IN OMX_BUFFERHEADERTYPE* buffer) {
95          LogNT::getInstance()->info(TAG, "FillBufferDone");
96          ImageOMX* image = static_cast<ImageOMX*>(buffer->pAppPrivate);
97          image->ReturnFillOMXBuffer(buffer);
98         return OMX_ErrorNone;
99 }
100
101 void ImageOMX::ReturnFillOMXBuffer(OMX_BUFFERHEADERTYPE* /*buffer*/)
102  {
103          //input_bufs_omx_mutex.lock();
104          omx_egl_filled = true;
105         //output_bufs_omx_full.push_back(buffer);
106         //input_bufs_omx_mutex.unlock();
107     VideoOMX* video = static_cast<VideoOMX*>(Video::getInstance());
108          video->signalOmx();
109  }
110
111
112 /*
113
114 int ImageOMX::play() {
115         if (!initted)
116                 return 0;
117         lastAType=MPTYPE_MPEG_Image;
118         Log::getInstance()->log("Image", Log::DEBUG, "enter play");
119
120         ((VideoOMX*)Video::getInstance())->interlaceSwitch4Demux(); // switch resolution if necessary
121
122         if (!AllocateCodecsOMX()) {
123                 return 0;
124         }
125         return 1;
126 }*/
127
128
129
130
131
132 int ImageOMX::AllocateCodecsOMX(unsigned char * buffer, unsigned int length)
133 {
134         OMX_ERRORTYPE error;
135         static OMX_CALLBACKTYPE callbacks= {&VideoOMX::EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
136
137         //LogNT::getInstance()->info(TAG, "Allocate Codecs OMX");
138         //Clock, move later to Image
139         VideoOMX* video = static_cast<VideoOMX*>(Video::getInstance());
140
141         OMX_PORT_PARAM_TYPE p_param;
142         memset(&p_param,0,sizeof(p_param));
143         p_param.nSize=sizeof(p_param);
144         p_param.nVersion.nVersion=OMX_VERSION;
145
146
147         video->LockClock();
148
149
150         error = OMX_GetHandle(&omx_imag_decode, L_VPE_OMX_IMAGE_DECODER, NULL, &callbacks);
151         if (error != OMX_ErrorNone) {
152                 LogNT::getInstance()->debug(TAG,
153                                 "Init OMX Image decoder failed %x", error);
154                 video->UnlockClock();
155                 return 0;
156         }
157
158
159
160         error = OMX_GetParameter(omx_imag_decode, OMX_IndexParamImageInit, &p_param);
161         if (error != OMX_ErrorNone) {
162                 LogNT::getInstance()->debug(TAG,
163                                 "Init OMX Image rend OMX_GetParameter failed %x", error);
164                 video->UnlockClock();
165                 return 0;
166         }
167         omx_image_input_port = p_param.nStartPortNumber;
168         omx_image_output_port = p_param.nStartPortNumber+1;
169
170
171
172
173         OMX_IMAGE_PARAM_PORTFORMATTYPE ft_type;
174         memset(&ft_type,0,sizeof(ft_type));
175         ft_type.nSize=sizeof(ft_type);
176         ft_type.nVersion.nVersion=OMX_VERSION;
177
178         ft_type.nPortIndex=omx_image_input_port;
179
180         switch (curformat)
181         {
182         case Jpeg: ft_type.eCompressionFormat=OMX_IMAGE_CodingJPEG;
183         break;
184         case PNG: ft_type.eCompressionFormat=OMX_IMAGE_CodingPNG;
185         break;
186
187         case Unsupported:
188           ;
189         }
190
191
192         error=OMX_SetParameter(omx_imag_decode,OMX_IndexParamImagePortFormat,&ft_type);
193         if (error!=OMX_ErrorNone){
194                 LogNT::getInstance()->debug(TAG, "Init OMX_IndexParamVImagePortFormat failed %x", error);
195                 video->UnlockClock();
196                 return 0;
197         }
198
199         if (!video->DisablePort(omx_imag_decode,omx_image_input_port) || !video->DisablePort(omx_imag_decode,omx_image_output_port)) {
200                 LogNT::getInstance()->debug(TAG, "Disable Ports OMX Image decoder failed");
201                 video->UnlockClock();
202                 return 0;
203         }
204
205
206         if (!video->ChangeComponentState(omx_imag_decode,OMX_StateIdle)) {
207                 LogNT::getInstance()->debug(TAG, "image decode idle ChangeComponentState");
208                 video->UnlockClock();
209                 return 0;
210         }
211
212
213
214         if (!PrepareInputBufsOMX(true, buffer, length)) {
215                 video->UnlockClock();
216                 LogNT::getInstance()->debug(TAG, "prepare input bufs failed");
217                 return 0;
218         }
219
220
221
222
223
224
225
226         if (!video->ChangeComponentState(omx_imag_decode,OMX_StateExecuting)) {
227                 LogNT::getInstance()->debug(TAG, "omx_image_decode ChangeComponentState Execute");
228                 video->UnlockClock();
229                 return 0;
230         }
231
232
233
234
235         if (!video->EnablePort(omx_imag_decode,omx_image_input_port,false)
236                                         ) {
237                 LogNT::getInstance()->debug(TAG, "Enable Ports OMXdecoder inputfailed");
238                 video->UnlockClock();
239                 return 0;
240         }
241
242
243
244
245         video->UnlockClock();
246         omx_running=true;
247
248
249
250         //LogNT::getInstance()->debug(TAG, "Allocate Codecs OMX finished");
251
252         return 1;
253 }
254
255
256
257
258
259
260 unsigned char* ImageOMX::decodePicture(LoadIndex index, unsigned char * buffer, unsigned int length, bool freemem)
261 {
262         if (pictInfValid) return buffer; // does support only one image at a Time;
263 //      LogNT::getInstance()->debug(TAG,
264 //                                      "decodePicture 1");
265         EGLPictureCreator * pictcreat =dynamic_cast<EGLPictureCreator*>(Osd::getInstance());
266         curformat=Unsupported;
267         if (buffer[0]== 0xff && buffer[1] ==0xd8) curformat=Jpeg;
268         if (buffer[0]== 0x89 && buffer[1] ==0x50 && buffer[2] ==0x4e) curformat=PNG;
269
270         if (curformat == Unsupported)   return buffer; // Jpeg magic numbers
271 //      LogNT::getInstance()->debug(TAG,
272 //                                              "decodePicture 2");
273         VideoOMX* video = static_cast<VideoOMX*>(Video::getInstance());
274
275
276         if (!pictcreat) return NULL;
277         int oldcancelstate;
278         int oldcanceltype;
279         pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldcancelstate);
280         pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldcanceltype);
281
282         if (!AllocateCodecsOMX(buffer,length)) {
283                 DeAllocateCodecsOMX();
284                 pthread_setcancelstate(oldcancelstate, NULL);
285                 pthread_setcanceltype(oldcanceltype, NULL);
286                 return NULL;
287         }
288         bool ret=intDecodePicture(index, buffer, length, pictcreat, video);
289         DeAllocateCodecsOMX();
290         pthread_setcancelstate(oldcancelstate, NULL);
291         pthread_setcanceltype(oldcanceltype, NULL);
292         if (ret && freemem) free(buffer);
293
294         if (ret) return NULL;
295         else return buffer;
296 }
297
298
299 bool ImageOMX::intDecodePicture(LoadIndex index, unsigned char* /* buffer */, unsigned int length, EGLPictureCreator* pictcreat, VideoOMX *video)
300 {
301         static OMX_CALLBACKTYPE callbacks= {&VideoOMX::EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
302
303         // Use Buffer
304         OMX_BUFFERHEADERTYPE * bufhead;
305
306         input_bufs_omx_mutex.lock();
307         int count =0;
308         while (input_bufs_omx_free.size()==0) {
309                 input_bufs_omx_mutex.unlock();
310                 //LogNT::getInstance()->debug(TAG, "DMP mark 6");
311                 //LogNT::getInstance()->debug(TAG, "Deliver MediaPacket no free sample");
312                 //return 0; // we do not have a free media sample
313
314                 count++;
315                 if (count>100) return false;
316                 MILLISLEEP(10);
317
318                 input_bufs_omx_mutex.lock();
319
320         }
321         bufhead=input_bufs_omx_free.front();
322         bufhead->nFilledLen=length;
323         //bufhead->nAllocLen= length;
324         bufhead->nOffset=0;
325         bufhead->nTimeStamp=VideoOMX::intToOMXTicks(0);
326         //bufhead->pBuffer=buffer;
327         bufhead->pAppPrivate=this;
328         input_bufs_omx_free.pop_front();
329         input_bufs_omx_mutex.unlock();
330
331
332         bufhead->nFilledLen=length;//bufhead->nAllocLen;
333         bufhead->nFlags=OMX_BUFFERFLAG_EOS;
334         video->ProtOMXEmptyThisBuffer(omx_imag_decode, bufhead);
335
336
337
338         video->LockClock();
339 //      LogNT::getInstance()->debug(TAG,
340 //                      "decodePicture 3");
341
342         video->WaitForEvent(omx_imag_decode,OMX_EventPortSettingsChanged);
343
344         OMX_ERRORTYPE error;
345
346         OMX_PARAM_PORTDEFINITIONTYPE port_def_type;
347         memset(&port_def_type,0,sizeof(port_def_type));
348         port_def_type.nSize=sizeof(port_def_type);
349         port_def_type.nVersion.nVersion=OMX_VERSION;
350         port_def_type.nPortIndex=omx_image_output_port;
351 //      LogNT::getInstance()->debug(TAG,
352 //                      "decodePicture 3a");
353
354         error=OMX_GetParameter(omx_imag_decode,OMX_IndexParamPortDefinition, &port_def_type);
355         if (error != OMX_ErrorNone) {
356                 LogNT::getInstance()->debug(TAG,
357                                 "OMX_IndexParamPortDefinition fix failed {:#x}", error);
358                 video->UnlockClock();
359                 return false;
360         }
361 //      LogNT::getInstance()->debug(TAG,
362 //                      "decodePicture 4");
363
364
365
366
367
368
369
370
371 /*
372         video->DisablePort(omx_imag_decode,omx_image_output_port,false);
373         LogNT::getInstance()->debug(TAG,
374                         "decodePicture 5");
375
376         if ( !video->CommandFinished(omx_imag_decode,OMX_CommandPortDisable,omx_image_output_port)) {
377                 video->UnlockClock();
378                 LogNT::getInstance()->debug(TAG, "commandfinishes end iop");
379                 return false;
380         }*/
381
382         switch (curformat)
383         {
384         case Jpeg:
385                 port_def_type.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar;
386                 port_def_type.format.image.nSliceHeight = 16;
387                 port_def_type.format.image.nStride = 0;
388                 break;
389         case PNG:
390                 //port_def_type.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar;
391                 //port_def_type.format.image.nSliceHeight = 32;
392                 //port_def_type.format.image.nStride = 0;
393                 port_def_type.format.image.nFrameHeight+=-(port_def_type.format.image.nFrameHeight%32); // The OpenMax png part is broken for the last slice
394                 // so we cut the broken part, not nice but works
395                 break;
396
397         case Unsupported:
398                 ;
399         }
400
401
402
403
404
405         error = OMX_SetParameter(omx_imag_decode, OMX_IndexParamPortDefinition,
406                         &port_def_type);
407         if (error != OMX_ErrorNone) {
408                 LogNT::getInstance()->debug(TAG,
409                                 "Set OMX_IndexParamPortDefinition1 failed {:#x}", error);
410                 video->UnlockClock();
411                 return false;
412         }
413
414
415 //      Log::getInstance()->log("Image", Log::DEBUG,
416 //                      "decodePicture 5 6");
417         error=OMX_GetHandle(&omx_egl_render,L_VPE_OMX_EGL_REND,NULL,&callbacks);
418
419         if (error!=OMX_ErrorNone){
420                 LogNT::getInstance()->debug(TAG, "Init OMX EGL renderer failed {:#x}", error);
421                 video->UnlockClock();
422                 return false;
423         }
424
425         OMX_PORT_PARAM_TYPE p_param;
426         memset(&p_param,0,sizeof(p_param));
427         p_param.nSize=sizeof(p_param);
428         p_param.nVersion.nVersion=OMX_VERSION;
429
430         error=OMX_GetParameter(omx_egl_render,OMX_IndexParamVideoInit,&p_param);
431         if (error!=OMX_ErrorNone){
432                 LogNT::getInstance()->debug(TAG, "Init OMX EGL renderer OMX_GetParameter failed {:#x}", error);
433                 video->UnlockClock();
434                 return false;
435         }
436         omx_egl_input_port=p_param.nStartPortNumber;
437         omx_egl_output_port=p_param.nStartPortNumber+1;
438
439
440
441
442         if (!video->DisablePort(omx_egl_render,omx_egl_input_port) || !video->DisablePort(omx_egl_render,omx_egl_output_port)) {
443                 LogNT::getInstance()->debug(TAG, "Disable Ports OMX Image decoder failed");
444                 video->UnlockClock();
445                 return false;
446         }
447
448
449         if (!video->ChangeComponentState(omx_egl_render,OMX_StateIdle)) {
450                 LogNT::getInstance()->debug(TAG, "egl render idle ChangeComponentState");
451                 video->UnlockClock();
452                 return false;
453         }
454
455
456
457         //Setuo chain
458
459 /*      if ( !video->CommandFinished(omx_egl_render,OMX_CommandPortDisable,omx_egl_input_port)) {
460                 video->UnlockClock();
461                 LogNT::getInstance()->debug(TAG, "commandfinishes end eip");
462                 return false;
463         }*/
464
465
466
467
468         /*      port_def_type.nPortIndex=omx_egl_input_port;
469         error = OMX_SetParameter(omx_egl_render, OMX_IndexParamPortDefinition,
470                                 &port_def_type);
471         if (error != OMX_ErrorNone) {
472                 LogNT::getInstance()->debug(TAG,
473                                 "Set OMX_IndexParamPortDefinition3 failed {:#x}", error);
474                 video->UnlockClock();
475                 pthread_setcancelstate(oldcancelstate, NULL);
476                 pthread_setcanceltype(oldcanceltype, NULL);
477                 return false;
478         }*/
479
480         pictInf.width = port_def_type.format.image.nFrameWidth;
481         pictInf.height = port_def_type.format.image.nFrameHeight;
482         pictInf.decoder = this;
483         pictInf.type = OsdVector::PictureInfo::RGBAMemBlock;
484         pictInf.lindex = index;
485
486
487         port_def_type.nPortIndex=omx_egl_output_port;
488
489         error=OMX_GetParameter(omx_egl_render,OMX_IndexParamPortDefinition, &port_def_type);
490         if (error != OMX_ErrorNone) {
491                 LogNT::getInstance()->debug(TAG,
492                                 "OMX_IndexParamPortDefinition fix failed {:#x}", error);
493                 video->UnlockClock();
494                 return false;
495         }
496
497
498
499         port_def_type.nBufferCountActual = 1;
500         EGLDisplay egl_display;
501         if (!pictcreat->getEGLPicture(pictInf, &egl_display)) {
502                 LogNT::getInstance()->debug(TAG,
503                                 "getEGLPict failed");
504                 video->UnlockClock();
505                 return false;
506         }
507         LogNT::getInstance()->debug(TAG,
508                         "getEGLPict {:#x}", (long) pictInf.reference);
509
510         port_def_type.format.video.pNativeWindow = egl_display;
511         error = OMX_SetParameter(omx_egl_render, OMX_IndexParamPortDefinition,
512                         &port_def_type);
513         if (error != OMX_ErrorNone) {
514                 LogNT::getInstance()->debug(TAG,
515                                 "Set OMX_IndexParamPortDefinition3 failed {:#x}", error);
516                 video->UnlockClock();
517                 return false;
518         }
519
520
521
522
523
524
525
526
527
528
529         error=OMX_SetupTunnel(omx_imag_decode,omx_image_output_port,omx_egl_render,omx_egl_input_port);
530         if (error!=OMX_ErrorNone){
531                 LogNT::getInstance()->debug(TAG, "OMX_Setup tunnel decode to egl rend failed");
532                 video->UnlockClock();
533                 return 0;
534         }
535
536         if (!video->EnablePort(omx_imag_decode,omx_image_output_port,false) || !video->EnablePort(omx_egl_render,omx_egl_input_port,false)
537         ) {
538                 LogNT::getInstance()->debug(TAG, "Enable Ports OMXdecoder rend failed");
539                 video->UnlockClock();
540                 return 0;
541         }
542
543         if ( !video->CommandFinished(omx_imag_decode,OMX_CommandPortEnable,omx_image_output_port)) {
544                 video->UnlockClock();
545                 LogNT::getInstance()->debug(TAG, "commandfinishes end iop");
546                 return 0;
547         }
548
549         if ( !video->CommandFinished(omx_egl_render,OMX_CommandPortEnable,omx_egl_input_port)) {
550                 video->UnlockClock();
551                 LogNT::getInstance()->debug(TAG, "commandfinishes end eip");
552                 return 0;
553         }
554
555 //      LogNT::getInstance()->debug(TAG,
556 //                      "decodePicture 7");
557         video->WaitForEvent(omx_egl_render,OMX_EventPortSettingsChanged);
558
559         LogNT::getInstance()->debug(TAG,
560                         "decodePicture 8");
561
562
563
564
565
566
567
568         error=OMX_SendCommand(omx_egl_render/*dec*/,OMX_CommandPortEnable,omx_egl_output_port/*codec*/,0);
569         if (error!=OMX_ErrorNone){
570                 LogNT::getInstance()->debug(TAG, "Prepare omx_egl_output_port Send Command to enable port {:#x}", error);
571                 return 0;
572         }
573
574
575         error=OMX_UseEGLImage(omx_egl_render/*dec*/,&buf_head_egl,omx_egl_output_port/*codec*/, this, pictInf.reference);
576         if (error!=OMX_ErrorNone){
577                 LogNT::getInstance()->debug(TAG, "Use OMX_UseEGLImage failed {:#x}", error);
578                 video->UnlockClock();
579                 return false;
580         }
581         buf_head_egl->pAppPrivate=this;
582
583 //      LogNT::getInstance()->debug(TAG,
584 //                      "decodePicture 8 a");
585
586         video->EnablePort(omx_imag_decode,omx_image_output_port,false);
587
588         if (!video->CommandFinished(omx_egl_render/*dec*/,OMX_CommandPortEnable, omx_egl_output_port /*codec*/)) {
589                 video->UnlockClock();
590                 return false;
591         }
592
593
594
595
596         LogNT::getInstance()->debug(TAG,
597                         "decodePicture 8 end");
598
599         if (!video->ChangeComponentState(omx_egl_render,OMX_StateExecuting)) {
600                 LogNT::getInstance()->debug(TAG, "omx_egl_rendd ChangeComponentState Execute");
601                 video->UnlockClock();
602                 return false;
603         }
604
605
606 //      LogNT::getInstance()->debug(TAG,
607 //                      "decodePicture 9");
608         //video->EnablePort(omx_egl_render,omx_egl_output_port,false);
609
610 //      LogNT::getInstance()->debug(TAG,
611 //                      "decodePicture 10");
612
613         omx_egl_filled = false;
614         error = OMX_FillThisBuffer(omx_egl_render, buf_head_egl);
615
616         if (error!=OMX_ErrorNone){
617                 LogNT::getInstance()->debug(TAG, "OMX_FillThisBuffer failed {:#x}", error);
618                 video->UnlockClock();
619                 return false;
620         }
621         count =1;
622         video->UnlockClock();
623         while (!omx_egl_filled) {
624
625                 count++;
626                 if (count>500) {
627                         LogNT::getInstance()->debug(TAG, "No one filled my buffer");
628                         return false;
629                 }
630                 MILLISLEEP(1);
631
632
633         }
634         omx_egl_filled = false;
635
636 //      LogNT::getInstance()->debug(TAG,
637 //                      "decodePicture left");
638
639
640
641         pictInfValid=true;
642         return true;
643
644 }
645
646 bool ImageOMX::getDecodedPicture(struct OsdVector::PictureInfo& pict_inf)
647 {
648         if (!pictInfValid) return false;
649         pict_inf=pictInf;
650         pictInfValid = false;
651         return true;
652 }
653
654 void ImageOMX::freeReference(void* /* ref */)
655 {
656 }
657
658 int ImageOMX::PrepareInputBufsOMX(bool setportdef, unsigned char * buffer, unsigned int length) //needs to be called with locvke omx clock mutex
659 {
660         VideoOMX* video = static_cast<VideoOMX*>(Video::getInstance());
661         OMX_ERRORTYPE error;
662         OMX_PARAM_PORTDEFINITIONTYPE port_def_type;
663         memset(&port_def_type,0,sizeof(port_def_type));
664         port_def_type.nSize=sizeof(port_def_type);
665         port_def_type.nVersion.nVersion=OMX_VERSION;
666         port_def_type.nPortIndex=omx_image_input_port;//omx_codec_input_port;
667
668         error=OMX_GetParameter(omx_imag_decode/*dec*/,OMX_IndexParamPortDefinition, &port_def_type);
669
670         if (error!=OMX_ErrorNone){
671                         LogNT::getInstance()->debug(TAG, "Get OMX OMX_IndexParamPortDefinition failed {:#x}", error);
672         }
673
674
675         if (setportdef) {
676                 port_def_type.nBufferCountActual=port_def_type.nBufferCountMin;
677                 port_def_type.nBufferSize=max(port_def_type.nBufferSize,length); // for transcoder important
678
679                 error=OMX_SetParameter(omx_imag_decode/*dec*/,OMX_IndexParamPortDefinition, &port_def_type);
680
681                 if (error!=OMX_ErrorNone){
682                         LogNT::getInstance()->debug(TAG, "Set OMX OMX_IndexParamPortDefinition failed {:#x}", error);
683                 }
684         }
685
686
687         error=OMX_SendCommand(omx_imag_decode/*dec*/,OMX_CommandPortEnable,omx_image_input_port/*codec*/,0);
688         if (error!=OMX_ErrorNone){
689                 LogNT::getInstance()->debug(TAG, "Prepare Input bufs Send Command to enable port {:#x}", error);
690                 return 0;
691         }
692
693         input_bufs_omx_mutex.lock();
694         for (unsigned int i=0; i< port_def_type.nBufferCountActual;i++) {
695                 OMX_BUFFERHEADERTYPE *buf_head=NULL;
696                 error=OMX_UseBuffer(omx_imag_decode/*dec*/,&buf_head,omx_image_input_port/*codec*/,this,port_def_type.nBufferSize, buffer);
697                 if (error!=OMX_ErrorNone){
698                         LogNT::getInstance()->debug(TAG, "Use OMX_UseBuffer failed {:#x}", error);
699                         input_bufs_omx_mutex.unlock();
700                         return 0;
701                 }
702                 input_bufs_omx_all.push_back(buf_head);
703                 input_bufs_omx_free.push_back(buf_head);
704         }
705         omx_first_frame=true;
706
707
708         input_bufs_omx_mutex.unlock();
709
710         if (!video->CommandFinished(omx_imag_decode/*dec*/,OMX_CommandPortEnable, omx_image_input_port /*codec*/)) {
711                 return 0;
712         }
713
714         return 1;
715 }
716
717 int ImageOMX::DestroyInputBufsOMX() //call with clock mutex locked
718 {
719         OMX_ERRORTYPE error;
720
721         input_bufs_omx_mutex.lock();
722         for (UINT i=0; i< input_bufs_omx_all.size();i++) {
723                 LogNT::getInstance()->debug(TAG, "OMX_FreeBuffer mark");
724                 //if (input_bufs_omx_all[i]->pBuffer) free(input_bufs_omx_all[i]->pBuffer);
725                 input_bufs_omx_all[i]->pBuffer=NULL;
726                 error=OMX_FreeBuffer(omx_imag_decode/*dec*/,omx_image_input_port/*codec*/,input_bufs_omx_all[i]);
727                 if (error!=OMX_ErrorNone){
728                         LogNT::getInstance()->debug(TAG, "Use OMX_FreeBuffer failed {:#x}", error);
729                         input_bufs_omx_mutex.unlock();
730                         return 0;
731                 }
732
733         }
734         input_bufs_omx_all.clear();
735         input_bufs_omx_free.clear();
736         input_bufs_omx_mutex.unlock();
737
738         return 1;
739 }
740
741 int ImageOMX::DestroyInputBufsOMXwhilePlaying() //call with clock mutex locked
742 {
743         //OMX_ERRORTYPE error;
744
745         input_bufs_omx_mutex.lock();
746         while (input_bufs_omx_all.size()>0) {
747                 if (input_bufs_omx_free.size()>0) {
748                         // Destroy one buffer
749                         std::vector<OMX_BUFFERHEADERTYPE*>::iterator itty=input_bufs_omx_all.begin();
750                         OMX_BUFFERHEADERTYPE* cur_buf=input_bufs_omx_free.front();
751                         for (; itty!= input_bufs_omx_all.end();itty++) {
752                                 if ((*itty)==cur_buf) {
753                                         input_bufs_omx_all.erase(itty);
754                                         input_bufs_omx_free.pop_front();
755                                         break;
756                                 }
757                         }
758                 } else {
759                         input_bufs_omx_mutex.unlock();
760                         MILLISLEEP(5);
761                         input_bufs_omx_mutex.lock();
762                 }
763         }
764
765         LogNT::getInstance()->debug(TAG, "DestroyInputBufsOMXwhilePlaying {} {}", input_bufs_omx_all.size(),input_bufs_omx_free.size());
766         input_bufs_omx_mutex.unlock();
767         return 1;
768 }
769
770
771 int ImageOMX::DeAllocateCodecsOMX()
772 {
773         OMX_ERRORTYPE error;
774         omx_running=false;
775         VideoOMX* video = static_cast<VideoOMX*>(Video::getInstance());
776 //       LogNT::getInstance()->debug(TAG, "enter deallocatecodecsomx");
777
778
779
780 //   LogNT::getInstance()->debug(TAG, "deallocatecodecsomx mark 1");
781
782 //   LogNT::getInstance()->debug(TAG, "deallocatecodecsomx mark 2");
783
784    video->LockClock();
785         if (omx_imag_decode/*dec*/) {
786
787
788                 if (!video->ChangeComponentState(omx_imag_decode,OMX_StateIdle)) {
789                         LogNT::getInstance()->debug(TAG, "omx_imag_decode ChangeComponentState");
790                 }
791
792                 if (omx_egl_render) {
793
794                         if (!video->ChangeComponentState(omx_egl_render,OMX_StateIdle)) {
795                                 LogNT::getInstance()->debug(TAG, "omx_egl_render ChangeComponentState");
796                         }
797                         /*if (!video->ChangeComponentState(omx_egl_render,OMX_StateLoaded,false)) {
798                                 LogNT::getInstance()->debug(TAG, "omx_egl_render ChangeComponentState");
799                         }*/
800                 }
801
802         /*      if (!video->ChangeComponentState(omx_imag_decode,OMX_StateLoaded,false)) {
803                         LogNT::getInstance()->debug(TAG, "omx_imag_decode ChangeComponentState");
804                 }*/
805
806
807
808         // TODO proper deinit sequence
809                 // first flush all buffers
810
811
812
813 //              LogNT::getInstance()->debug(TAG, "deallocatecodecsomx mark 3");
814
815                 error=OMX_SendCommand(omx_imag_decode,OMX_CommandFlush, omx_image_output_port, NULL);
816                 if (error!=OMX_ErrorNone) {
817                         LogNT::getInstance()->debug(TAG, "OMX_Flush rend in failed {:#x}", error);
818
819                 }
820
821                 if (omx_egl_render) {
822
823                         if (!video->ChangeComponentState(omx_egl_render,OMX_StateIdle)) {
824                                 LogNT::getInstance()->debug(TAG, "omx_egl_render ChangeComponentState");
825                         }
826
827 //                      LogNT::getInstance()->debug(TAG, "deallocatecodecsomx mark 4");
828
829                         error=OMX_SendCommand(omx_egl_render,OMX_CommandFlush, omx_egl_input_port, NULL);
830                         if (error!=OMX_ErrorNone) {
831                                 LogNT::getInstance()->debug(TAG, "OMX_Flush rend in failed {:#x}", error);
832
833                         }
834
835 //                      LogNT::getInstance()->debug(TAG, "deallocatecodecsomx mark 5");
836
837                         error=OMX_SendCommand(omx_egl_render,OMX_CommandFlush, omx_egl_output_port, NULL);
838                         if (error!=OMX_ErrorNone) {
839                                 LogNT::getInstance()->debug(TAG, "OMX_Flush rend in failed {:#x}", error);
840
841                         }
842
843 //                      Log::getInstance()->log("Image", Log::DEBUG, "deallocatecodecsomx mark 6");
844
845                         if (!video->CommandFinished(omx_egl_render,OMX_CommandFlush,omx_egl_input_port) ||
846                                         !video->CommandFinished(omx_egl_render,OMX_CommandFlush,omx_egl_output_port)) {
847                                 LogNT::getInstance()->debug(TAG, "flush cmd clock shed failed");
848                         }
849 //                      LogNT::getInstance()->debug(TAG, "deallocatecodecsomx mark 6 a");
850                 }
851                 error=OMX_SendCommand(omx_imag_decode,OMX_CommandFlush, omx_image_input_port, NULL);
852                 if (error!=OMX_ErrorNone) {
853                         LogNT::getInstance()->debug(TAG, "OMX_Flush rend in failed {:#x}", error);
854
855                 }
856
857                 if (buf_head_egl) {
858                         error=OMX_FreeBuffer(omx_egl_render/*dec*/, omx_egl_output_port/*codec*/,buf_head_egl);
859                         if (error!=OMX_ErrorNone){
860                                 LogNT::getInstance()->debug(TAG, "Use OMX_FreeBuffer 2 failed {:#x}", error);
861                         }
862                 }
863
864                 buf_head_egl=NULL;
865
866
867 //              LogNT::getInstance()->debug(TAG, "deallocatecodecsomx mark 6 b");
868
869                 if (!video->CommandFinished(omx_imag_decode,OMX_CommandFlush,omx_image_input_port) ||
870                                 !video->CommandFinished(omx_imag_decode,OMX_CommandFlush,omx_image_output_port) ) {
871                         LogNT::getInstance()->debug(TAG, "flush cmd clock shed failed");
872                 }
873
874 //              LogNT::getInstance()->debug(TAG, "deallocatecodecsomx mark 6 c");
875
876
877                 DestroyInputBufsOMX(); //We have to make sure that no buffers are in use
878
879 //              LogNT::getInstance()->debug(TAG, "deallocatecodecsomx mark 7");
880
881                 //todo flushing
882                 if (!video->DisablePort(omx_imag_decode,omx_image_output_port,true)) {
883                         LogNT::getInstance()->debug(TAG, "Disable Tunnel Port failed 1");
884                 }
885
886                 if (omx_egl_render) {
887
888                         if (!video->DisablePort(omx_egl_render,omx_egl_input_port,true)) {
889                                 LogNT::getInstance()->debug(TAG, "Disable Tunnel Port failed 4");
890                         }
891
892
893                         error=OMX_SetupTunnel(omx_imag_decode,omx_image_output_port,NULL,0);
894                         if (error!=OMX_ErrorNone) {
895                                 LogNT::getInstance()->debug(TAG, "OMX_Setup tunnel teardown failed {:#x}", error);
896
897                         }
898
899                         error=OMX_SetupTunnel(omx_egl_render,omx_egl_input_port,NULL,0);
900                         if (error!=OMX_ErrorNone) {
901                                 LogNT::getInstance()->debug(TAG, "OMX_Setup tunnel teardown failed {:#x}", error);
902
903                         }
904                 }
905
906
907 //              LogNT::getInstance()->debug(TAG, "deallocatecodecsomx mark 8");
908
909
910                 //error=OMX_FreeHandle(omx_aud_dec);
911                 error=OMX_FreeHandle(omx_imag_decode);
912                 if (error!=OMX_ErrorNone) {
913                         LogNT::getInstance()->debug(TAG, "FreeHandle failed {}", error);
914                 }
915                 if (omx_egl_render) {
916                         error=OMX_FreeHandle(omx_egl_render);
917                         if (error!=OMX_ErrorNone) {
918                                 LogNT::getInstance()->debug(TAG, "FreeHandle failed {}", error);
919                         }
920                 }
921                 video->UnlockClock();
922
923                 video->clearEventsForComponent(omx_imag_decode);
924                 video->clearEventsForComponent(omx_egl_render); // removes spurious error messages
925                 omx_imag_decode/*dec*/=NULL;
926                 omx_egl_render/*dec*/=NULL;
927
928         } else  {
929
930                 video->UnlockClock();
931         }
932 //        LogNT::getInstance()->debug(TAG, "leave deallocate codecs OMX");
933
934         return 1;
935 }