2 Copyright 2004-2005 Chris Tallon, 2009 Marten Richter
4 This file is part of VOMP.
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.
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.
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.
21 #include "videovpeogl.h"
23 #include "mtdraspberry.h"
25 #include "osdopengl.h"
30 //A lot of parts of this file are heavily inspired by xbmc omx implementations
32 VideoVPEOGL::VideoVPEOGL()
36 #ifdef VPE_OMX_SUPPORT
40 cur_input_buf_omx=NULL;
41 omx_h264=omx_mpeg2=true;
44 #ifdef VPE_LIBAV_SUPPORT
45 mpeg2codec_context_libav=NULL;
47 dec_frame_libav_uploading_framebuf=NULL;
48 dec_frame_libav_decoding=NULL;
49 ogl_frame_outside=false;
50 //decoding_mode=VPE_NO_XVMC;
51 decoding_mode=VPE_XVMC_MOCOMP;
52 //decoding_mode=VPE_XVMC_IDCT;
57 ogl_forward_ref_frame_num=0;
58 ogl_backward_ref_frame_num=0;
59 ogl_forward_ref_frame=NULL;
60 ogl_backward_ref_frame=NULL;
69 VideoVPEOGL::~VideoVPEOGL()
74 int VideoVPEOGL::init(UCHAR tformat)
76 if (initted) return 0;
79 // if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
81 if (!setFormat(tformat)) { shutdown(); return 0; }
82 if (!setConnection(COMPOSITERGB)) { shutdown(); return 0; }
83 if (!setAspectRatio(ASPECT4X3)) { shutdown(); return 0; }
84 if (!setMode(NORMAL)) { shutdown(); return 0; }
85 if (!setSource()) { shutdown(); return 0; }
86 if (!attachFrameBuffer()) { shutdown(); return 0; }
90 /* if (format == PAL) setLetterboxBorder("38");
91 else setLetterboxBorder("31");*/
105 int VideoVPEOGL::initUsingOSDObjects()
107 EGLDisplay i_egl_display;
108 EGLSurface i_egl_surface;
109 EGLContext i_egl_context;
110 EGLConfig i_egl_config;
111 OsdOpenGL *osd=(OsdOpenGL*)osd->getInstance();
112 osd->getEGLObjs(&i_egl_display,&i_egl_surface,&i_egl_context, &i_egl_config);
113 const EGLint attr_context[]={
114 EGL_CONTEXT_CLIENT_VERSION,2,
118 egl_display=i_egl_display;
119 egl_context=eglCreateContext(egl_display,i_egl_config,i_egl_context,attr_context);
120 if (egl_context==EGL_NO_CONTEXT) {
121 Log::getInstance()->log("Video", Log::WARN, "Creating egl context failed! %x",eglGetError());
124 // We create a dummy surface here, in order to allow two contexts
125 const EGLint attr_pbuffer[]={
126 EGL_WIDTH, 1, EGL_HEIGHT,1,
129 egl_surface=eglCreatePbufferSurface(egl_display,i_egl_config,attr_pbuffer);
130 if (egl_surface==EGL_NO_SURFACE) {
131 Log::getInstance()->log("Video", Log::WARN, "Creating egl pbuffer failed! %x",eglGetError());
138 //egl_surface=i_egl_surface;
139 //egl_context=i_egl_context;
142 #ifdef VPE_OMX_SUPPORT
143 // we are called before the audio
146 if (error!=OMX_ErrorNone) {
147 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX failed %x", error);
151 //our callbacks move to play?
155 #ifdef VPE_LIBAV_SUPPORT
158 if (decoding_mode==VPE_NO_XVMC) {
159 mpeg2codec_libav=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO);
161 mpeg2codec_libav=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO_XVMC);
163 if (mpeg2codec_libav==NULL) {
164 Log::getInstance()->log("Video", Log::DEBUG, "Find libav mpeg2 codec failed");
174 #ifdef VPE_OMX_SUPPORT
176 OMX_ERRORTYPE VideoVPEOGL::EventHandler_OMX(OMX_IN OMX_HANDLETYPE handle,OMX_IN OMX_PTR appdata,
177 OMX_IN OMX_EVENTTYPE event_type,OMX_IN OMX_U32 data1,
178 OMX_IN OMX_U32 data2,OMX_IN OMX_PTR event_data) {
180 Log::getInstance()->log("Video", Log::NOTICE, "eventHandler %x %x %x %x %x",handle,event_type,data1,data2,event_data);
182 struct VPE_OMX_EVENT new_event;
183 new_event.handle=handle;
184 new_event.appdata=appdata;
185 new_event.event_type=event_type;
186 new_event.data1=data1;
187 new_event.data2=data2;
188 new_event.event_data=event_data;
190 VideoVPEOGL *video=(VideoVPEOGL *)getInstance();
191 video->AddOmxEvent(new_event);
193 /* switch (event_type) {
194 case OMX_EventCmdComplete: {
199 return OMX_ErrorNone;
203 void VideoVPEOGL::AddOmxEvent(VPE_OMX_EVENT new_event)
205 omx_event_mutex.Lock();
206 omx_events.push_back(new_event);
207 omx_event_mutex.Unlock();
211 OMX_ERRORTYPE VideoVPEOGL::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer){
213 Log::getInstance()->log("Video", Log::NOTICE, "EmptyBufferDone");
214 VideoVPEOGL *video=(VideoVPEOGL *)getInstance();
215 video->ReturnEmptyOMXBuffer(buffer);
216 return OMX_ErrorNone;
220 void VideoVPEOGL::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){
221 input_bufs_omx_mutex.Lock();
222 Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size());
223 input_bufs_omx_free.push_back(buffer);
224 Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size());
225 input_bufs_omx_mutex.Unlock();
228 OMX_ERRORTYPE VideoVPEOGL::FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer) {
229 Log::getInstance()->log("Video", Log::NOTICE, "FillBufferDone");
230 return OMX_ErrorNone;
235 int VideoVPEOGL::shutdown()
237 if (!initted) return 0;
242 #ifdef VPE_OMX_SUPPORT
243 DeAllocateCodecsOMX();
246 #ifdef VPE_LIBAV_SUPPORT
247 DeAllocateCodecsLibav();
249 eglDestroyContext(egl_display,egl_context);
254 int VideoVPEOGL::AllocateYUV400OglTexture(VPEOGLFrame* outframe,int width,int height,int stride)
256 Log::getInstance()->log("Video", Log::NOTICE, "Allocate ogl texture 400");
258 glGenTextures(1, &outframe->textures[0]);
259 glBindTexture(GL_TEXTURE_2D, outframe->textures[0]);
260 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, stride, height, 0, GL_LUMINANCE,
261 GL_UNSIGNED_BYTE, NULL);
263 glGenTextures(1, &outframe->textures[1]);
264 glBindTexture(GL_TEXTURE_2D, outframe->textures[1]);
265 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, stride>>1, height>>1, 0, GL_LUMINANCE,
266 GL_UNSIGNED_BYTE, NULL);
268 glGenTextures(1, &outframe->textures[2]);
269 glBindTexture(GL_TEXTURE_2D, outframe->textures[2]);
270 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, stride>>1, height>>1, 0, GL_LUMINANCE,
271 GL_UNSIGNED_BYTE, NULL);
272 outframe->height=height;
273 outframe->width=width;
274 outframe->stride=stride;
279 int VideoVPEOGL::AllocateYUV444OglTexture(VPEOGLFrame* outframe,int width,int height,int stride)
281 Log::getInstance()->log("Video", Log::NOTICE, "Allocate ogl texture 444");
283 glGenTextures(1, &outframe->textures[0]);
284 glBindTexture(GL_TEXTURE_2D, outframe->textures[0]);
285 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
286 GL_UNSIGNED_BYTE, NULL);
287 outframe->textures[1]=outframe->textures[2]=0; // no handles here
293 outframe->height=height;
294 outframe->width=width;
295 outframe->stride=stride;// does not make any sense otherwise, just to prevent reallocating
300 VPEOGLFrame *VideoVPEOGL::getReadyOGLFrame(){
301 VPEOGLFrame *return_obj=NULL;
302 ogl_frame_mutex.Lock();
303 if (ready_ogl_frames.size()>0) {
304 return_obj=ready_ogl_frames.front();
305 ready_ogl_frames.pop_front();
306 //Log::getInstance()->log("Video", Log::WARN, "readyOGLRFrame markoutgoing num: %d",return_obj->pict_num);
307 ogl_frame_outside=true;
309 ogl_frame_mutex.Unlock();
313 void VideoVPEOGL::returnOGLFrame(VPEOGLFrame *frame)
315 ogl_frame_mutex.Lock();
317 ogl_frame_outside=false;
318 //Log::getInstance()->log("Video", Log::WARN, "returnOGLRFrame mark incoming num: %d",frame->pict_num);
319 if (frame->pict_num==ogl_forward_ref_frame_num ||
320 frame->pict_num==ogl_backward_ref_frame_num ) {
321 recycle_ref_ogl_frames.push_back(frame);
323 free_ogl_frames.push_back(frame);
326 ogl_frame_mutex.Unlock();
329 void VideoVPEOGL::recycleOGLRefFrames()
331 // This function recycles frames formerly used as reference frame
332 ogl_frame_mutex.Lock();
333 list<VPEOGLFrame*> keep;
334 list<VPEOGLFrame*>::iterator itty=recycle_ref_ogl_frames.begin();
335 while (itty!=recycle_ref_ogl_frames.end()) {
336 // Log::getInstance()->log("Video", Log::WARN, "recycleOGLRefFrame mark3");
337 if ((*itty)->pict_num==ogl_forward_ref_frame_num
338 || (*itty)->pict_num==ogl_backward_ref_frame_num)
340 // ok we have to keep this
341 keep.push_back(*itty);
343 free_ogl_frames.push_back(*itty);
347 recycle_ref_ogl_frames.clear();
348 recycle_ref_ogl_frames=keep;
350 ogl_frame_mutex.Unlock();
355 void VideoVPEOGL::threadMethod()
357 if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {
358 Log::getInstance()->log("Video", Log::WARN, "Making egl Current failed in thread %d",eglGetError());
367 #ifdef VPE_LIBAV_SUPPORT
368 dec_frame_libav_mutex.Lock();
369 AVFrame* dec_frame_libav_uploading_int=NULL;
372 if (dec_frame_libav_upload_and_view_pending.size()>0 ) {
374 dec_frame_libav_uploading_int=dec_frame_libav_upload_and_view_pending.front();
375 dec_frame_libav_uploading_framebuf=(VPE_FrameBuf*)dec_frame_libav_uploading_int->base[0];
376 //Log::getInstance()->log("Video", Log::WARN, "threadMethod u and view %d %lld %x",(dec_frame_libav_uploading_framebuf)->pict_num,run,
377 // dec_frame_libav_uploading_framebuf);
378 // if (dec_frame_libav_upload_only_pending.size()>0) Log::getInstance()->log("Video", Log::WARN, "threadMethod u and view2 %d",
379 // ((VPE_FrameBuf*)dec_frame_libav_upload_only_pending.front())->pict_num);
382 if ((dec_frame_libav_uploading_framebuf)->ogl_uploaded || decoding_mode==VPE_NO_XVMC ) {
383 dec_frame_libav_upload_and_view_pending.pop_front();
384 if (decoding_mode==VPE_NO_XVMC) upload=true;
386 dec_frame_libav_uploading_framebuf=NULL;
387 dec_frame_libav_uploading_int=NULL; // if not uploaded do not do it yet
388 view=false; //do the upload
389 // Log::getInstance()->log("Video", Log::WARN, "threadMethod u and view view canceled");
393 if (!view && dec_frame_libav_upload_only_pending.size()>0) { //this is for uploading reference frames ahead
395 dec_frame_libav_uploading_framebuf=dec_frame_libav_upload_only_pending.front();
396 //Log::getInstance()->log("Video", Log::WARN, "threadMethod u %d %lld %x",((VPE_FrameBuf*)dec_frame_libav_uploading_framebuf)->pict_num,run,
397 // dec_frame_libav_uploading_framebuf);
398 dec_frame_libav_upload_only_pending.pop_front();
401 /* if (((VPE_FrameBuf*)dec_frame_libav_uploading->base[0])->ogl_uploaded) {
403 dec_frame_libav_uploading=NULL; //do not upload again
412 if (dec_frame_libav_upload_and_view_pending.size()>0
413 ||dec_frame_libav_upload_only_pending.size()>0) sleep=false;
415 dec_frame_libav_mutex.Unlock();
418 if (dec_frame_libav_uploading_framebuf) {
420 //Code Block for debugging if needed
421 /* Log::getInstance()->log("Video", Log::WARN, "Iterate all free ogl frames");
422 ogl_frame_mutex.Lock();
423 list<VPEOGLFrame*>::iterator itty=free_ogl_frames.begin();
424 while (itty!=free_ogl_frames.end()) {
425 Log::getInstance()->log("Video", Log::WARN, "free ogl pict num %d",(*itty)->pict_num);
430 itty=recycle_ref_ogl_frames.begin();
431 while (itty!=recycle_ref_ogl_frames.end()) {
432 Log::getInstance()->log("Video", Log::WARN, "recycle ogl pict num %d",(*itty)->pict_num);
436 itty=ready_ogl_frames.begin();
437 while (itty!=ready_ogl_frames.end()) {
438 Log::getInstance()->log("Video", Log::WARN, "ready ogl pict num %d",(*itty)->pict_num);
442 ogl_frame_mutex.Unlock();*/
446 int width,height,pixfmt;
447 //First get a free ogl image
448 VPEOGLFrame* out_frame=NULL;
451 ogl_frame_mutex.Lock();
452 // Log::getInstance()->log("Video", Log::WARN, "threadMethod mark upload 1a %d %d %d %d %d",all_ogl_frames.size(),free_ogl_frames.size(),
453 // recycle_ref_ogl_frames.size(),ready_ogl_frames.size(),ogl_frame_outside);
454 if (all_ogl_frames.size()==0) {
455 ogl_frame_mutex.Unlock(); break;
458 if (free_ogl_frames.size()>0) {
462 out_frame=free_ogl_frames.front();
463 free_ogl_frames.pop_front();
465 ogl_frame_mutex.Unlock();
468 ogl_frame_mutex.Lock();
470 // if (msleep)Log::getInstance()->log("Video", Log::WARN, "msleep FPS %d",msleep);
471 ogl_frame_mutex.Unlock();
475 // Log::getInstance()->log("Video", Log::WARN, "outframes old pict num: %d",out_frame->pict_num);
476 if (out_frame->textures[0]==0 || out_frame->width!=width ||
477 out_frame->height!=height || out_frame->stride!=dec_frame_libav_uploading_framebuf->stride) {
478 if (out_frame->textures[0]!=0) {
479 glDeleteTextures(1,&out_frame->textures[0]);
480 out_frame->textures[0]=0;
482 if (out_frame->textures[1]!=0) {
483 glDeleteTextures(1,&out_frame->textures[1]);
484 out_frame->textures[1]=0;
486 if (out_frame->textures[2]!=0) {
487 glDeleteTextures(1,&out_frame->textures[2]);
488 out_frame->textures[2]=0;
491 if (decoding_mode==VPE_NO_XVMC) {
492 if (!AllocateYUV400OglTexture(out_frame,width,height,dec_frame_libav_uploading_framebuf->stride)) failed=true;
494 if (!AllocateYUV444OglTexture(out_frame,width,height,dec_frame_libav_uploading_framebuf->stride)) failed=true; //We use a YUV 444 texture in this case
495 // the shaders are easier to implement
498 dec_frame_libav_uploading_framebuf->ogl_ref=out_frame;
499 dec_frame_libav_uploading_framebuf->ogl_uploaded=true;
503 //up to now only YUV data, this is for reference only, since the pi is too slow.
504 if (decoding_mode==VPE_NO_XVMC) {
505 glBindTexture(GL_TEXTURE_2D, out_frame->textures[0]);
506 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
507 glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
508 out_frame->stride,out_frame->height,
509 GL_LUMINANCE,GL_UNSIGNED_BYTE,
510 dec_frame_libav_uploading_framebuf->data[0]);
512 glBindTexture(GL_TEXTURE_2D, out_frame->textures[1]);
513 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
514 glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
515 out_frame->stride>>1,out_frame->height>>1,
516 GL_LUMINANCE,GL_UNSIGNED_BYTE,
517 dec_frame_libav_uploading_framebuf->data[1]);
519 glBindTexture(GL_TEXTURE_2D, out_frame->textures[2]);
520 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
521 glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
522 out_frame->stride>>1,out_frame->height>>1,
523 GL_LUMINANCE,GL_UNSIGNED_BYTE,
524 dec_frame_libav_uploading_framebuf->data[2]);
527 xvmc_pix_fmt * pix_fmt=(xvmc_pix_fmt *)dec_frame_libav_uploading_framebuf->data[2];
528 if (moco_shader && pix_fmt) {
530 moco_shader->uploadDataBlocks(pix_fmt->data_blocks,pix_fmt->next_free_data_block_num,
531 pix_fmt->mv_blocks , pix_fmt->filled_mv_blocks_num );
532 // Log::getInstance()->log("Video", Log::WARN, "Pictnum %d Forward %d Backward %d ",pix_fmt->p_surface,
533 // pix_fmt->p_past_surface,pix_fmt->p_future_surface);
535 if (((int)pix_fmt->p_future_surface)!=0 && ogl_backward_ref_frame_num!=((int)pix_fmt->p_future_surface))
537 //Now determine the frame, that fits
538 ogl_frame_mutex.Lock();
540 for (int i=0;i<all_ogl_frames.size();i++) {
541 if (all_ogl_frames[i]->pict_num==((int)pix_fmt->p_future_surface))
543 ogl_forward_ref_frame=ogl_backward_ref_frame; //mpeg life time axioms
544 ogl_forward_ref_frame_num=ogl_backward_ref_frame_num;
545 ogl_backward_ref_frame=all_ogl_frames[i];
546 ogl_backward_ref_frame_num=(int)pix_fmt->p_future_surface;
551 // if (!found) {// for debugging
552 // Log::getInstance()->log("Video", Log::WARN, "Emergency reference frame not found");
556 ogl_frame_mutex.Unlock();
557 recycleOGLRefFrames(); //needed for recycling of reference frames
559 // Log::getInstance()->log("Video", Log::WARN, "Pictnum mark1");
562 if ( ((int)pix_fmt->p_past_surface)==ogl_backward_ref_frame_num)
567 if (((int)pix_fmt->p_past_surface)!=0 && ogl_forward_ref_frame_num!=((int)pix_fmt->p_past_surface))
569 //Now determine the frame, that fits
570 ogl_frame_mutex.Lock();
572 for (int i=0;i<all_ogl_frames.size();i++) {
573 if (all_ogl_frames[i]->pict_num==((int)pix_fmt->p_past_surface))
575 ogl_forward_ref_frame=all_ogl_frames[i];
576 ogl_forward_ref_frame_num=(int)pix_fmt->p_past_surface; // This should not happen, or for DMV, who knows
582 // Log::getInstance()->log("Video", Log::WARN, "Emergency reference frame not found %d %d",ogl_forward_ref_frame_num,
583 // ((int)pix_fmt->p_past_surface));
587 ogl_frame_mutex.Unlock();
588 recycleOGLRefFrames(); //needed for recycling of reference frames
591 //Log::getInstance()->log("Video", Log::WARN, "Pictnum mark2");
593 if (decoding_mode==VPE_XVMC_MOCOMP)
600 out_frame->pict_num=dec_frame_libav_uploading_framebuf->pict_num;
602 // Log::getInstance()->log("Video", Log::WARN, "Pictnum mark3");
604 moco_shader->doMoCo(out_frame,(((int)pix_fmt->p_past_surface)!=0)? ogl_forward_ref_frame:NULL,
605 (((int)pix_fmt->p_future_surface)!=0)? ogl_backward_ref_frame:NULL);
607 //Log::getInstance()->log("Video", Log::WARN, "Pictnum mark4");
608 // Excute motion compensation
610 //Log::getInstance()->log("Video", Log::WARN, "moco pixfmt error abort");
626 //Log::getInstance()->log("Video", Log::WARN, "threadMethod mark view");
627 VPEOGLFrame* out_frame=dec_frame_libav_uploading_framebuf->ogl_ref;
628 xvmc_pix_fmt * pix_fmt=(xvmc_pix_fmt *)dec_frame_libav_uploading_framebuf->data[2];
629 /* Log::getInstance()->log("Video", Log::WARN, "View Pictnum %d Forward %d Backward %d pict_num %d",pix_fmt->p_surface,
630 pix_fmt->p_past_surface,pix_fmt->p_future_surface,out_frame->pict_num);
631 Log::getInstance()->log("Video", Log::WARN, "Real Pictnum %d ",out_frame->pict_num);*/
633 releaseFrameBufUpload(dec_frame_libav_uploading_framebuf);
634 ogl_frame_mutex.Lock();
635 ready_ogl_frames.push_back(out_frame);
636 ogl_frame_mutex.Unlock();
637 ((OsdOpenGL*)Osd::getInstance())->AdviseAboutNewFrame(); //Tell him, that we have a frame waiting
639 dec_frame_libav_mutex.Lock();
640 dec_frame_libav_free.push_back(dec_frame_libav_uploading_int);
641 dec_frame_libav_mutex.Unlock();
645 dec_frame_libav_mutex.Lock();
646 dec_frame_libav_uploading_framebuf=NULL;
648 if (dec_frame_libav_upload_and_view_pending.size()>0
649 ||dec_frame_libav_upload_only_pending.size()>0) sleep=false;
651 dec_frame_libav_mutex.Unlock();
659 struct timespec target_time;
661 clock_gettime(CLOCK_REALTIME,&target_time);
662 target_time.tv_nsec+=1000000LL*ts;
663 if (target_time.tv_nsec>999999999) {
664 target_time.tv_nsec-=1000000000L;
665 target_time.tv_sec+=1;
667 threadWaitForSignalTimed(&target_time);
668 //Log::getInstance()->log("Video", Log::WARN, "threadMethod signalled FPS");
676 void VideoVPEOGL::threadPostStopCleanup()
678 eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
679 #ifdef VPE_LIBAV_SUPPORT
680 dec_frame_libav_uploading_framebuf=NULL;
687 int VideoVPEOGL::setTVsize(UCHAR ttvsize)
691 // Override the aspect ratio usage, temporarily use to set the video chip mode
692 if (!setAspectRatio(tvsize)) { shutdown(); return 0; }
694 if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
695 if (!setSource()) { shutdown(); return 0; }
696 if (!attachFramebuffer()) { shutdown(); return 0; }
698 // Reopening the fd causes the scart aspect line to go back to 4:3
699 // Set this again to the same as the tv screen size
700 if (!setAspectRatio(tvsize)) { shutdown(); return 0; }
702 // mode == LETTERBOX is invalid if the TV is widescreen
703 if (tvsize == ASPECT16X9) setMode(NORMAL);
708 int VideoVPEOGL::setDefaultAspect()
710 return setAspectRatio(tvsize);
715 int VideoVPEOGL::setFormat(UCHAR tformat)
717 if (!initted) return 0;
718 if ((tformat != PAL) && (tformat != NTSC)) return 0;
721 // if (ioctl(fdVideo, AV_SET_VID_DISP_FMT, format) != 0) return 0;
737 int VideoVPEOGL::setConnection(UCHAR tconnection)
739 if (!initted) return 0;
740 if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;
741 connection = tconnection;
743 // if (ioctl(fdVideo, AV_SET_VID_OUTPUT, connection) != 0) return 0;
747 int VideoVPEOGL::setAspectRatio(UCHAR taspectRatio)
749 if (!initted) return 0;
750 if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
751 aspectRatio = taspectRatio;
753 Log::getInstance()->log("Video", Log::DEBUG, "Setting aspect to %i", aspectRatio);
755 // if (ioctl(fdVideo, AV_SET_VID_RATIO, aspectRatio) != 0) return 0;
759 int VideoVPEOGL::setMode(UCHAR tmode)
761 if (!initted) return 0;
763 if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode
765 if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH)
766 && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0;
769 // if (ioctl(fdVideo, AV_SET_VID_MODE, mode) != 0) return 0;
773 int VideoVPEOGL::signalOff()
775 // if (ioctl(fdVideo, AV_SET_VID_DENC, 0) != 0) return 0;
779 int VideoVPEOGL::signalOn()
781 // if (ioctl(fdVideo, AV_SET_VID_DENC, 1) != 0) return 0;
785 int VideoVPEOGL::setSource()
787 if (!initted) return 0;
789 // What does this do...
790 // if (ioctl(fdVideo, AV_SET_VID_SRC, 1) != 0) return 0;
794 int VideoVPEOGL::setPosition(int x, int y)
796 if (!initted) return 0;
798 // vid_pos_regs_t pos_d;
802 /* vid_pos_regs_t pos_d;
804 memset(&pos_d, 0, sizeof(pos_d));
829 pos_d.y = 100; // Top left X
830 pos_d.x = 50; // Top left Y
838 // if (ioctl(fdVideo, AV_SET_VID_POSITION, &pos_d) != 0) return 0;
842 int VideoVPEOGL::sync()
844 if (!initted) return 0;
846 // if (ioctl(fdVideo, AV_SET_VID_SYNC, 2) != 0) return 0;
853 int VideoVPEOGL::play()
855 if (!initted) return 0;
857 #ifdef VPE_OMX_SUPPORT
860 if (!omx_h264) doomx=false;
862 if (!omx_mpeg2) doomx=false;
865 if (AllocateCodecsOMX()) {
866 decoding_backend=VPE_DECODER_OMX;
868 // Otherwise fall back to libav
872 Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX failed assume h264 unsupported");
875 Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX failed assume mpeg2 unsupported");
880 #ifdef VPE_LIBAV_SUPPORT
881 if (AllocateCodecsLibav()) {
882 decoding_backend=VPE_DECODER_libav;
884 // Otherwise fall back to libav
893 #ifdef VPE_OMX_SUPPORT
894 int VideoVPEOGL::AllocateCodecsOMX()
897 static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
899 Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX");
900 //Clock, move later to audio
904 error=OMX_GetHandle(&omx_clock,VPE_OMX_CLOCK,NULL,&callbacks);
907 if (error!=OMX_ErrorNone){
908 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX clock failed %x", error);
909 DeAllocateCodecsOMX();
915 OMX_PORT_PARAM_TYPE p_param;
916 memset(&p_param,0,sizeof(p_param));
917 p_param.nSize=sizeof(p_param);
918 p_param.nVersion.nVersion=OMX_VERSION;
919 error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param);
920 if (error!=OMX_ErrorNone){
921 Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error);
922 DeAllocateCodecsOMX();
925 omx_clock_output_port=p_param.nStartPortNumber;
927 for (unsigned int i=0;i<p_param.nPorts;i++) {
928 if (!DisablePort(omx_clock,p_param.nStartPortNumber+i) ) {
929 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX clock failed %d",i);
930 DeAllocateCodecsOMX();
936 OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
937 memset(&clock_conf,0,sizeof(clock_conf));
938 clock_conf.nSize=sizeof(clock_conf);
939 clock_conf.nVersion.nVersion=OMX_VERSION;
940 clock_conf.eState=OMX_TIME_ClockStateWaitingForStartTime;
941 clock_conf.nStartTime=0;
942 clock_conf.nOffset=0;
943 clock_conf.nWaitMask=OMX_CLOCKPORT0;
944 error=OMX_SetParameter(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
945 if (error!=OMX_ErrorNone){
946 Log::getInstance()->log("Video", Log::DEBUG, "Clock IndexConfigTimeClockState failed %x", error);
947 DeAllocateCodecsOMX();
954 error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_H264_DECODER,NULL,&callbacks);
956 error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_MPEG2_DECODER,NULL,&callbacks);
959 if (error!=OMX_ErrorNone){
960 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video decoder failed %x", error);
961 DeAllocateCodecsOMX();
967 memset(&p_param,0,sizeof(p_param));
968 p_param.nSize=sizeof(p_param);
969 p_param.nVersion.nVersion=OMX_VERSION;
970 error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamVideoInit,&p_param);
971 if (error!=OMX_ErrorNone){
972 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX h264 decoder OMX_GetParameter failed %x", error);
973 DeAllocateCodecsOMX();
976 omx_codec_input_port=p_param.nStartPortNumber;
977 omx_codec_output_port=p_param.nStartPortNumber+1;
979 if (!DisablePort(omx_vid_dec,omx_codec_input_port) || !DisablePort(omx_vid_dec,omx_codec_output_port)) {
980 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video decoder failed");
981 DeAllocateCodecsOMX();
986 OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE conceal;
987 memset(&conceal,0,sizeof(conceal));
988 conceal.nSize=sizeof(conceal);
989 conceal.nVersion.nVersion=OMX_VERSION;
990 conceal.bStartWithValidFrame=OMX_FALSE;
992 error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamBrcmVideoDecodeErrorConcealment,&conceal);
993 if (error!=OMX_ErrorNone){
994 Log::getInstance()->log("Video", Log::DEBUG, "OMX_IndexParamBrcmVideoDecodeErrorConcealment failed %x", error);
995 DeAllocateCodecsOMX();
1000 error=OMX_GetHandle(&omx_vid_sched,VPE_OMX_VIDEO_SCHED,NULL,&callbacks);
1001 if (error!=OMX_ErrorNone){
1002 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler failed %x", error);
1003 DeAllocateCodecsOMX();
1009 error=OMX_GetParameter(omx_vid_sched,OMX_IndexParamVideoInit,&p_param);
1010 if (error!=OMX_ErrorNone){
1011 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler OMX_GetParameter failed %x", error);
1012 DeAllocateCodecsOMX();
1015 omx_shed_input_port=p_param.nStartPortNumber;
1016 omx_shed_output_port=p_param.nStartPortNumber+1;
1019 error=OMX_GetParameter(omx_vid_sched,OMX_IndexParamOtherInit,&p_param);
1020 if (error!=OMX_ErrorNone){
1021 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler OMX_GetParameter failed %x", error);
1022 DeAllocateCodecsOMX();
1025 omx_shed_clock_port=p_param.nStartPortNumber;
1028 if (!DisablePort(omx_vid_sched,omx_shed_input_port) || !DisablePort(omx_vid_sched,omx_shed_output_port)
1029 || !DisablePort(omx_vid_sched,omx_shed_clock_port)) {
1030 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video shed failed");
1031 DeAllocateCodecsOMX();
1036 error=OMX_GetHandle(&omx_vid_rend,VPE_OMX_VIDEO_REND,NULL,&callbacks);
1037 if (error!=OMX_ErrorNone){
1038 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video rend failed %x", error);
1039 DeAllocateCodecsOMX();
1043 error=OMX_GetParameter(omx_vid_rend,OMX_IndexParamVideoInit,&p_param);
1044 if (error!=OMX_ErrorNone){
1045 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video rend OMX_GetParameter failed %x", error);
1046 DeAllocateCodecsOMX();
1049 omx_rend_input_port=p_param.nStartPortNumber;
1050 //omx_rend_output_port=p_param.nStartPortNumber+1;
1053 if (!DisablePort(omx_vid_rend,omx_rend_input_port) /*|| !DisablePort(omx_vid_rend,omx_rend_output_port)*/
1055 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video rend failed");
1056 DeAllocateCodecsOMX();
1069 /* error=OMX_SendCommand(omx_vid_dec,OMX_CommandStateSet,OMX_StateIdle,0);
1070 if (error!=OMX_ErrorNone){
1071 Log::getInstance()->log("Video", Log::DEBUG, "vid_dec Send Command to OMX State Idle %x", error);
1078 OMX_VIDEO_PARAM_PORTFORMATTYPE ft_type;
1079 memset(&ft_type,0,sizeof(ft_type));
1080 ft_type.nSize=sizeof(ft_type);
1081 ft_type.nVersion.nVersion=OMX_VERSION;
1083 ft_type.nPortIndex=omx_codec_input_port;
1085 ft_type.eCompressionFormat=OMX_VIDEO_CodingAVC;
1087 ft_type.eCompressionFormat=OMX_VIDEO_CodingMPEG2;
1090 Demuxer* demux=Demuxer::getInstance();
1092 ft_type.xFramerate=0;//25*(1<<16);//demux->getFrameRate()*(1<<16);
1093 Log::getInstance()->log("Video", Log::DEBUG, "Framerate: %d",demux->getFrameRate());
1094 error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamVideoPortFormat,&ft_type);
1095 if (error!=OMX_ErrorNone){
1096 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexParamVideoPortFormat failed %x", error);
1097 DeAllocateCodecsOMX();
1102 if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) {
1103 Log::getInstance()->log("Video", Log::DEBUG, "vid_dec ChangeComponentState");
1104 DeAllocateCodecsOMX();
1109 if (!PrepareInputBufsOMX()) {
1110 DeAllocateCodecsOMX();
1115 if (!ChangeComponentState(omx_clock,OMX_StateIdle)) {
1116 Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Idle");
1117 DeAllocateCodecsOMX();
1121 error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,omx_vid_sched,omx_shed_clock_port);
1122 if (error!=OMX_ErrorNone){
1123 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);
1124 DeAllocateCodecsOMX();
1128 if (!EnablePort(omx_clock,omx_clock_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_clock_port,false)
1130 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX clock shed failed");
1131 DeAllocateCodecsOMX();
1135 if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_clock_port)) {
1136 DeAllocateCodecsOMX();
1140 error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,omx_vid_sched,omx_shed_input_port);
1141 if (error!=OMX_ErrorNone){
1142 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel dec to sched failed %x", error);
1143 DeAllocateCodecsOMX();
1149 if (!EnablePort(omx_vid_dec,omx_codec_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_input_port,false)
1151 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX codec shed failed");
1152 DeAllocateCodecsOMX();
1156 if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_input_port)) {
1159 if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) {
1160 Log::getInstance()->log("Video", Log::DEBUG, "vid_sched idle ChangeComponentState");
1161 DeAllocateCodecsOMX();
1164 if (!CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port)
1165 ||!CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_output_port)){
1166 DeAllocateCodecsOMX();
1170 if (!ChangeComponentState(omx_vid_dec,OMX_StateExecuting)) {
1171 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_dec ChangeComponentState Execute");
1172 DeAllocateCodecsOMX();
1176 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_output_port,omx_vid_rend,omx_rend_input_port);
1177 if (error!=OMX_ErrorNone){
1178 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel sched to rend failed %x", error);
1179 DeAllocateCodecsOMX();
1183 if (!EnablePort(omx_vid_sched,omx_shed_output_port,false) || !EnablePort(omx_vid_rend,omx_rend_input_port,false)
1185 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX shed rend failed");
1186 DeAllocateCodecsOMX();
1190 if (!CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_output_port)
1191 || !CommandFinished(omx_vid_rend,OMX_CommandPortEnable,omx_rend_input_port)) {
1192 DeAllocateCodecsOMX();
1196 if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) {
1197 Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState");
1198 DeAllocateCodecsOMX();
1203 if (!ChangeComponentState(omx_vid_sched,OMX_StateExecuting)) {
1204 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_sched ChangeComponentState Execute");
1205 DeAllocateCodecsOMX();
1209 if (!ChangeComponentState(omx_vid_rend,OMX_StateExecuting)) {
1210 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_rend ChangeComponentState Execute");
1211 DeAllocateCodecsOMX();
1216 OMX_CONFIG_DISPLAYREGIONTYPE dispconf;
1217 memset(&dispconf,0,sizeof(dispconf));
1218 dispconf.nSize=sizeof(dispconf);
1219 dispconf.nVersion.nVersion=OMX_VERSION;
1221 dispconf.nPortIndex=omx_rend_input_port;
1223 dispconf.set=OMX_DISPLAY_SET_LAYER ;
1225 error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
1226 if (error!=OMX_ErrorNone){
1227 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
1228 DeAllocateCodecsOMX();
1232 /* dispconf.set=OMX_DISPLAY_SET_FULLSCREEN ;
1233 dispconf.fullscreen=OMX_FALSE;
1234 error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
1235 if (error!=OMX_ErrorNone){
1236 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
1237 DeAllocateCodecsOMX();
1241 dispconf.set=OMX_DISPLAY_SET_DEST_RECT;
1242 dispconf.dest_rect.x_offset=100;
1243 dispconf.dest_rect.y_offset=100;
1244 dispconf.dest_rect.width=640;
1245 dispconf.dest_rect.height=480;
1246 error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
1247 if (error!=OMX_ErrorNone){
1248 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
1249 DeAllocateCodecsOMX();
1256 if (!ChangeComponentState(omx_clock,OMX_StateExecuting)) {
1257 Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Exccute");
1258 DeAllocateCodecsOMX();
1268 int VideoVPEOGL::ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type)
1270 OMX_ERRORTYPE error;
1271 error=OMX_SendCommand(handle,OMX_CommandStateSet,type,0);
1272 if (error!=OMX_ErrorNone){
1273 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to OMX State %x %x",handle,type, error);
1277 if (!CommandFinished(handle,OMX_CommandStateSet,type)) {
1285 int VideoVPEOGL::EnablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait)
1287 OMX_ERRORTYPE error;
1288 error=OMX_SendCommand(handle,OMX_CommandPortEnable,port,0);
1289 if (error!=OMX_ErrorNone){
1290 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to enable port %x %x",handle,port, error);
1294 if (!wait) return 1;
1295 if (!CommandFinished(handle,OMX_CommandPortEnable,port)) {
1303 int VideoVPEOGL::DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait)
1305 OMX_ERRORTYPE error;
1306 error=OMX_SendCommand(handle,OMX_CommandPortDisable,port,0);
1307 if (error!=OMX_ErrorNone){
1308 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to disable port %x %x",handle,port, error);
1312 if (!wait) return 1;
1313 if (!CommandFinished(handle,OMX_CommandPortDisable,port)) {
1324 int VideoVPEOGL::CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2)
1328 omx_event_mutex.Lock();
1329 list<VPE_OMX_EVENT>::iterator itty=omx_events.begin();
1330 while (itty!=omx_events.end()) {
1332 VPE_OMX_EVENT current=*itty;
1333 if (current.handle==handle) { //this is ours
1334 if (current.event_type==OMX_EventError) {
1335 omx_events.erase(itty);
1336 omx_event_mutex.Unlock();
1339 } else if (current.event_type==OMX_EventCmdComplete && current.data1==command && current.data2==data2) {
1340 omx_events.erase(itty);
1341 omx_event_mutex.Unlock();
1348 omx_event_mutex.Unlock();
1353 Log::getInstance()->log("Video", Log::DEBUG, "CommandFinished waited too long %x %x %x",handle,command, data2);
1362 int VideoVPEOGL::PrepareInputBufsOMX()
1364 OMX_ERRORTYPE error;
1365 OMX_PARAM_PORTDEFINITIONTYPE port_def_type;
1366 memset(&port_def_type,0,sizeof(port_def_type));
1367 port_def_type.nSize=sizeof(port_def_type);
1368 port_def_type.nVersion.nVersion=OMX_VERSION;
1369 port_def_type.nPortIndex=omx_codec_input_port;
1371 error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type);
1373 if (error!=OMX_ErrorNone){
1374 Log::getInstance()->log("Video", Log::DEBUG, "Get OMX OMX_IndexParamPortDefinition failed %x", error);
1376 /* Log::getInstance()->log("Video", Log::DEBUG, "Port para %d %d %d %d %d %d %d", port_def_type.nBufferCountActual,
1377 port_def_type.nBufferCountMin,port_def_type.nBufferSize,port_def_type.bEnabled,port_def_type.bPopulated,
1378 port_def_type.bBuffersContiguous,port_def_type.nBufferAlignment);*/
1380 port_def_type.nBufferCountActual=60;
1382 error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type);
1384 if (error!=OMX_ErrorNone){
1385 Log::getInstance()->log("Video", Log::DEBUG, "Set OMX OMX_IndexParamPortDefinition failed %x", error);
1389 error=OMX_SendCommand(omx_vid_dec,OMX_CommandPortEnable,omx_codec_input_port,0);
1390 if (error!=OMX_ErrorNone){
1391 Log::getInstance()->log("Video", Log::DEBUG, "Prepare Input bufs Send Command to enable port %x", error);
1395 input_bufs_omx_mutex.Lock();
1396 for (unsigned int i=0; i< port_def_type.nBufferCountActual;i++) {
1398 // unsigned char* new_buffer_data=(unsigned char*)malloc(port_def_type.nbufferSize);
1399 OMX_BUFFERHEADERTYPE *buf_head=NULL;
1400 /* error=OMX_Usebuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nbufferSize,new_buffer_data);
1401 if (error!=OMX_ErrorNone){
1402 Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_Usebuffer failed %x", error);
1403 input_bufs_omx_mutex.Unlock();
1406 error=OMX_AllocateBuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nBufferSize);
1407 if (error!=OMX_ErrorNone){
1408 Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_AllocateBuffer failed %x", error);
1409 input_bufs_omx_mutex.Unlock();
1412 input_bufs_omx_all.push_back(buf_head);
1413 input_bufs_omx_free.push_back(buf_head);
1415 omx_first_frame=true;
1418 cur_input_buf_omx=NULL;
1419 input_bufs_omx_mutex.Unlock();
1422 Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark3");
1423 if (!CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_input_port)) {
1426 Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark4");
1431 int VideoVPEOGL::DestroyInputBufsOMX()
1433 OMX_ERRORTYPE error;
1435 cur_input_buf_omx=NULL;
1436 input_bufs_omx_mutex.Lock();
1437 for (int i=0; i< input_bufs_omx_all.size();i++) {
1438 // free(input_bufs_omx_all[i]->pBuffer);
1439 // input_bufs_omx_all[i]->pBuffer=NULL;
1440 error=OMX_FreeBuffer(omx_vid_dec,omx_codec_input_port,input_bufs_omx_all[i]);
1441 if (error!=OMX_ErrorNone){
1442 Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_FreeBuffer failed %x", error);
1443 input_bufs_omx_mutex.Unlock();
1447 input_bufs_omx_all.clear();
1448 input_bufs_omx_free.clear();
1449 input_bufs_omx_mutex.Unlock();
1456 int VideoVPEOGL::DeAllocateCodecsOMX()
1458 OMX_ERRORTYPE error;
1461 // first flush all buffers
1463 error=OMX_SendCommand(omx_vid_dec,OMX_CommandFlush, omx_codec_output_port, NULL);
1464 if (error!=OMX_ErrorNone){
1465 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush codec out failed %x", error);
1469 error=OMX_SendCommand(omx_vid_sched,OMX_CommandFlush, omx_shed_input_port, NULL);
1470 if (error!=OMX_ErrorNone){
1471 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush shed in failed %x", error);
1475 if (!CommandFinished(omx_vid_dec,OMX_CommandFlush,omx_codec_output_port) ||
1476 !CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_input_port)) {
1477 Log::getInstance()->log("Video", Log::DEBUG, "flush cmd codec shed failed");
1480 error=OMX_SendCommand(omx_clock,OMX_CommandFlush, omx_clock_output_port, NULL);
1481 if (error!=OMX_ErrorNone){
1482 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush clock out failed %x", error);
1486 error=OMX_SendCommand(omx_vid_sched,OMX_CommandFlush, omx_shed_clock_port, NULL);
1487 if (error!=OMX_ErrorNone){
1488 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush shed clock failed %x", error);
1492 if (!CommandFinished(omx_clock,OMX_CommandFlush,omx_clock_output_port) ||
1493 !CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_clock_port)) {
1494 Log::getInstance()->log("Video", Log::DEBUG, "flush cmd clock shed failed");
1497 error=OMX_SendCommand(omx_vid_sched,OMX_CommandFlush, omx_shed_output_port, NULL);
1498 if (error!=OMX_ErrorNone) {
1499 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush shed out failed %x", error);
1503 error=OMX_SendCommand(omx_vid_rend,OMX_CommandFlush, omx_rend_input_port, NULL);
1504 if (error!=OMX_ErrorNone) {
1505 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush rend in failed %x", error);
1509 if (!CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_output_port) ||
1510 !CommandFinished(omx_vid_rend,OMX_CommandFlush,omx_rend_input_port)) {
1511 Log::getInstance()->log("Video", Log::DEBUG, "flush cmd shed rend failed");
1517 error=OMX_SendCommand(omx_vid_dec,OMX_CommandFlush, omx_codec_input_port, NULL);
1518 if (error!=OMX_ErrorNone){
1519 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush codec out failed %x", error);
1524 if (!CommandFinished(omx_vid_dec,OMX_CommandFlush,omx_codec_input_port)) {
1525 Log::getInstance()->log("Video", Log::DEBUG, "flush cmd codec input failed");
1528 DestroyInputBufsOMX();
1531 if (!DisablePort(omx_vid_rend,omx_rend_input_port,true)) {
1532 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 1");
1534 if (!DisablePort(omx_vid_sched,omx_shed_output_port,true)) {
1535 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 2 ");
1538 error=OMX_SetupTunnel(omx_vid_rend,omx_rend_input_port,NULL,NULL);
1539 if (error!=OMX_ErrorNone){
1540 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1544 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_output_port,NULL,NULL);
1545 if (error!=OMX_ErrorNone){
1546 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1550 if (!DisablePort(omx_vid_sched,omx_shed_input_port,true)) {
1551 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 3");
1554 if (!DisablePort(omx_vid_sched,omx_shed_clock_port,true)) {
1555 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 4");
1558 if (!DisablePort(omx_clock,omx_clock_output_port,true)) {
1559 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 5");
1561 if (!DisablePort(omx_vid_dec,omx_codec_output_port,true)) {
1562 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 6");
1567 if (!DisablePort(omx_vid_dec,omx_codec_input_port,true)) {
1568 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 7");
1572 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_input_port,NULL,NULL);
1573 if (error!=OMX_ErrorNone){
1574 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1577 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_clock_port,NULL,NULL);
1578 if (error!=OMX_ErrorNone){
1579 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1583 error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,NULL,NULL);
1584 if (error!=OMX_ErrorNone){
1585 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1589 error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,NULL,NULL);
1590 if (error!=OMX_ErrorNone){
1591 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1599 error=OMX_FreeHandle(omx_vid_dec);
1600 error=OMX_FreeHandle(omx_vid_sched);
1601 error=OMX_FreeHandle(omx_vid_rend);
1602 error=OMX_FreeHandle(omx_clock);
1604 if (error!=OMX_ErrorNone) {
1605 Log::getInstance()->log("Video", Log::DEBUG, "FreeHandle failed %d", error);
1615 #ifdef VPE_LIBAV_SUPPORT
1617 enum PixelFormat VideoVPEOGL::get_format_libav(struct AVCodecContext *s, const enum PixelFormat *fmt)
1619 int dec_mode=((VideoVPEOGL*)getInstance())->getlibavDecodingMode();
1620 enum PixelFormat ret_pix=PIX_FMT_NONE;
1621 if (dec_mode==VPE_NO_XVMC) return PIX_FMT_NONE;
1622 while (*fmt!=PIX_FMT_NONE) {
1623 if (*fmt== PIX_FMT_XVMC_MPEG2_IDCT && dec_mode==VPE_XVMC_IDCT) {
1624 ret_pix=PIX_FMT_XVMC_MPEG2_IDCT;
1625 } else if (*fmt== PIX_FMT_XVMC_MPEG2_MC && dec_mode==VPE_XVMC_MOCOMP) {
1626 ret_pix=PIX_FMT_XVMC_MPEG2_MC;
1633 // we use this function to push the data to ogl out before hand, this is only useful for xvmc
1634 void VideoVPEOGL::draw_horiz_band_libav(struct AVCodecContext *s, const AVFrame *src, int offset[4], int y, int type, int height)
1636 if ((y+height)==src->height) {
1637 /* Log::getInstance()->log("Video", Log::NOTICE, "draw_horiz_band %d %d %d %d %d!",y,type,height,((xvmc_pix_fmt *)src->data[2])->p_surface,
1638 ((xvmc_pix_fmt *)src->data[2])->picture_structure);*/
1639 if (((xvmc_pix_fmt *)src->data[2])->picture_structure!=3) {
1640 Log::getInstance()->log("Video", Log::ERR, "Non frame pict not supported! Yet! Please send sample to authors!"); exit(0);
1642 ((VideoVPEOGL*)Video::getInstance())->add_dec_frame_upload_only(s,src);
1647 int VideoVPEOGL::reget_buffer_libav(struct AVCodecContext *c, AVFrame *pic)
1649 Log::getInstance()->log("Video", Log::ERR, "Buffer reusing! Should not happen!Not Implemented!");
1653 int VideoVPEOGL::get_buffer_libav(struct AVCodecContext *c, AVFrame *pic)
1655 unsigned int want_sizes[4]={0,0,0,0};
1657 bool normal_pixs=false;
1659 int num_dct_blocks=0;
1662 //reget logic from mplayer
1663 if (pic->opaque && pic->data[0] && (!pic->buffer_hints ||pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE )){
1664 Log::getInstance()->log("Video", Log::ERR, "Buffer reusing! Should not happen!");
1669 if (c->pix_fmt!=PIX_FMT_XVMC_MPEG2_IDCT &&c->pix_fmt!=PIX_FMT_XVMC_MPEG2_MC) {
1671 // standard pixel format
1672 // this is written using much inspiration from libav util.c, so portions from there
1678 avcodec_align_dimensions2(c, &width, &height, s_a);
1679 if ((c->flags & CODEC_FLAG_EMU_EDGE)==0) {
1683 // Now we have to determine alignment size
1684 bool unaligned=true;
1686 av_image_fill_linesizes(pict.linesize, c->pix_fmt, width); //linesizes are derived
1687 width+=width & ~(width-1); //trick from libav, now determine, if the alignment is ok
1689 for (int i=0;i<4;i++) {
1690 if ((pict.linesize[i]%s_a[i])!=0) {
1696 int tot_size=av_image_fill_pointers(pict.data, c->pix_fmt, height, NULL, pict.linesize); //get sizes
1697 for (int i=0;i<4 ;i++) {
1698 if (i<3 && pict.data[i+1]) {
1699 want_sizes[i]=pict.data[i+1]-pict.data[i];
1702 want_sizes[i]=(tot_size-(pict.data[i]-pict.data[0]));
1709 //TODO set linesizes!
1711 num_blocks=((c->width+15)/16)*((c->height+15)/16);
1712 num_dct_blocks=num_blocks*6; //6 blocks per macroblock
1714 want_sizes[2]=sizeof(xvmc_pix_fmt);
1715 want_sizes[1]=sizeof(short)*num_dct_blocks*8*8;
1716 want_sizes[0]=sizeof(XvMCMacroBlock)*num_blocks;
1717 pict.linesize[0]=pict.linesize[1]=pict.linesize[2]=pict.linesize[3]=0;
1721 VPE_FrameBuf *frame_buf=((VideoVPEOGL*)Video::getInstance())->getFrameBuf(want_sizes);
1722 frame_buf->ogl_ref=NULL; //do not use old references, crash instead!
1723 frame_buf->ogl_uploaded=false; //not uploaded yet
1724 frame_buf->width=pic->width;
1725 frame_buf->height=pic->height;
1726 frame_buf->stride=pic->linesize[0];
1728 //Log::getInstance()->log("Video", Log::NOTICE, "get buffer %x",frame_buf);
1730 Log::getInstance()->log("Video", Log::ERR, "Getting buffer libav failed");
1736 pic->type=FF_BUFFER_TYPE_USER; // we are controlling the buffers
1737 int hchr_shift,vchr_shift;
1738 avcodec_get_chroma_sub_sample(c->pix_fmt,&hchr_shift,&vchr_shift);
1739 const int pixel_size = av_pix_fmt_descriptors[c->pix_fmt].comp[0].step_minus1+1;
1740 for (int i=0;i<4;i++) {
1741 pic->data[i]=(uint8_t*)frame_buf->data[i];
1742 pic->linesize[i]=pict.linesize[i];
1748 edge_width>>=hchr_shift;
1749 edge_height>>=vchr_shift;
1751 pic->data[i]+=FFALIGN((pic->linesize[i]*16) + (pixel_size*edge_width), s_a[i]);
1755 pic->base[0]=(uint8_t*)frame_buf; // our structure
1756 //pic->extended_data=pic->data;
1757 if(c->pkt) pic->pkt_pts=c->pkt->pts;
1758 else pic->pkt_pts=AV_NOPTS_VALUE;
1759 pic->width=c->width;
1760 pic->height=c->height;
1761 pic->format=c->pix_fmt;
1762 pic->sample_aspect_ratio=c->sample_aspect_ratio;
1763 pic->reordered_opaque= c->reordered_opaque;
1766 xvmc_pix_fmt *pix_xvmc=(xvmc_pix_fmt *)pic->data[2];
1767 pix_xvmc->xvmc_id=AV_XVMC_ID;
1768 pix_xvmc->data_blocks=(short*)pic->data[1];
1769 pix_xvmc->mv_blocks=(XvMCMacroBlock*)pic->data[0];
1770 pix_xvmc->allocated_mv_blocks=num_blocks;
1771 pix_xvmc->allocated_data_blocks=num_dct_blocks;
1772 if (c->pix_fmt==PIX_FMT_XVMC_MPEG2_IDCT) pix_xvmc->idct=1;
1773 else pix_xvmc->idct=0;
1774 pix_xvmc->unsigned_intra=1; // let see what happens
1775 pix_xvmc->p_surface=(XvMCSurface*)frame_buf->pict_num;
1776 pix_xvmc->start_mv_blocks_num=0;
1777 pix_xvmc->filled_mv_blocks_num=0;
1778 pix_xvmc->next_free_data_block_num=0;
1788 void VideoVPEOGL::release_buffer_libav(struct AVCodecContext *c, AVFrame *pic)
1790 // Log::getInstance()->log("Video", Log::NOTICE, "release buffer %x",pic->base[0]);
1791 ((VideoVPEOGL*)Video::getInstance())->releaseFrameBufLibav((VPE_FrameBuf*) pic->base[0]);
1793 pic->data[0]=pic->data[1]=pic->data[2]=pic->data[3]=NULL;
1798 int VideoVPEOGL::AllocateCodecsLibav()
1800 if (libav_running) DeAllocateCodecsLibav();
1801 libav_hastime=false;
1802 Log::getInstance()->log("Video", Log::NOTICE, "AllocateCodecslibav");
1803 mpeg2codec_context_libav=avcodec_alloc_context();
1804 if (mpeg2codec_context_libav==NULL) {
1805 Log::getInstance()->log("Video", Log::DEBUG, "Creating libav codec context failed");
1808 if (decoding_mode!=VPE_NO_XVMC) {
1809 mpeg2codec_context_libav->slice_flags=SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
1810 if (decoding_mode==VPE_XVMC_MOCOMP) mpeg2codec_context_libav->pix_fmt=PIX_FMT_XVMC_MPEG2_MC;
1811 else mpeg2codec_context_libav->pix_fmt=PIX_FMT_XVMC_MPEG2_IDCT;
1812 mpeg2codec_context_libav->get_format=get_format_libav;
1813 mpeg2codec_context_libav->draw_horiz_band=draw_horiz_band_libav;
1816 mpeg2codec_context_libav->get_buffer=get_buffer_libav;
1817 mpeg2codec_context_libav->reget_buffer=reget_buffer_libav;
1818 mpeg2codec_context_libav->release_buffer=release_buffer_libav;
1822 int avc_ret=avcodec_open(mpeg2codec_context_libav, mpeg2codec_libav);
1824 Log::getInstance()->log("Video", Log::DEBUG, "Opening libav codec failed ");
1827 memset(&incom_packet_libav,0,sizeof(incom_packet_libav));
1828 incom_packet_libav_size=200000;
1829 incom_packet_libav.data=(uint8_t*)av_malloc(incom_packet_libav_size+FF_INPUT_BUFFER_PADDING_SIZE);
1831 dec_frame_libav_mutex.Lock();
1832 for (int i=0;i<3;i++) {
1833 AVFrame *dec_frame_libav=avcodec_alloc_frame(); // may be we need multiple frames, if we want to use async texture upload
1834 if (!dec_frame_libav) {
1835 Log::getInstance()->log("Video", Log::DEBUG, "Allocating dec_frame failed");
1838 dec_frame_libav_all.push_back(dec_frame_libav);
1839 dec_frame_libav_free.push_back(dec_frame_libav);
1841 dec_frame_libav_decoding=NULL;
1842 dec_frame_libav_mutex.Unlock();
1844 ogl_frame_mutex.Lock();
1845 //Allocate texture structs, since we do not know the sizes, we do not allocate the textures yet
1846 for (int i=0;i<5;i++) {
1847 VPEOGLFrame *new_frame=(VPEOGLFrame *)malloc(sizeof(VPEOGLFrame));
1848 new_frame->type=1; //1 = YUV, 2 RGB
1849 new_frame->textures[0]=0;
1850 new_frame->textures[1]=0;
1851 new_frame->textures[2]=0;
1852 new_frame->width=new_frame->height=0;
1853 all_ogl_frames.push_back(new_frame);
1854 free_ogl_frames.push_back(new_frame);
1857 ogl_frame_outside=false;
1859 ogl_frame_mutex.Unlock();
1861 if (decoding_mode==VPE_XVMC_MOCOMP) {
1862 OsdOpenGL* osd=(OsdOpenGL*)osd->getInstance();
1863 osd->BeginPainting(); // get OpenGl context
1864 moco_shader=new GLMocoShader();
1865 moco_shader->init();
1875 int VideoVPEOGL::DeAllocateCodecsLibav()
1877 libav_running=false;
1878 Log::getInstance()->log("Video", Log::NOTICE, "DeAllocateCodecslibav");
1879 dec_frame_libav_mutex.Lock();
1880 dec_frame_libav_upload_and_view_pending.clear();
1881 dec_frame_libav_upload_only_pending.clear();
1882 dec_frame_libav_free.clear();
1883 dec_frame_libav_mutex.Unlock();
1884 while (dec_frame_libav_uploading_framebuf) {
1885 Log::getInstance()->log("Video", Log::NOTICE, "Wait for uploading to finish");
1888 dec_frame_libav_mutex.Lock();
1889 for (int i=0; i< dec_frame_libav_all.size();i++) {
1890 av_free(dec_frame_libav_all[i]);
1893 dec_frame_libav_all.clear();
1895 av_free(incom_packet_libav.data);
1896 incom_packet_libav.data=NULL;
1897 incom_packet_libav_size=0;
1899 dec_frame_libav_mutex.Unlock();
1900 dec_frame_libav_decoding=NULL;
1901 while (ogl_frame_outside) {
1902 Log::getInstance()->log("Video", Log::NOTICE, "Wait for ogl frame from outside");
1906 ((OsdOpenGL*)Osd::getInstance())->BeginPainting(); // get osd's context
1907 ogl_frame_mutex.Lock();
1908 for (int i=0; i< dec_frame_libav_all.size();i++) {
1909 VPEOGLFrame * del_frame=all_ogl_frames[i];
1910 if (del_frame->textures[0]==0) {
1911 glDeleteTextures(1,&del_frame->textures[0]);
1912 del_frame->textures[0]=0;
1914 if (del_frame->textures[1]==0) {
1915 glDeleteTextures(1,&del_frame->textures[1]);
1916 del_frame->textures[1]=0;
1918 if (del_frame->textures[2]==0) {
1919 glDeleteTextures(1,&del_frame->textures[2]);
1920 del_frame->textures[2]=0;
1923 free(all_ogl_frames[i]);
1925 all_ogl_frames.clear();
1926 free_ogl_frames.clear();
1927 ready_ogl_frames.clear();
1928 recycle_ref_ogl_frames.clear();
1929 ogl_forward_ref_frame_num=0;
1930 ogl_backward_ref_frame_num=0;
1931 ogl_forward_ref_frame=NULL;
1932 ogl_backward_ref_frame=NULL;
1934 ogl_frame_mutex.Unlock();
1935 ((OsdOpenGL*)Osd::getInstance())->EndPainting();
1938 if (mpeg2codec_context_libav) {
1939 avcodec_close(mpeg2codec_context_libav);
1940 av_free(mpeg2codec_context_libav);
1941 mpeg2codec_context_libav=NULL;
1947 vpe_framebuf_mutex.Lock();
1949 for (int i=0;i<all_frame_bufs.size();i++) {
1950 VPE_FrameBuf* current=all_frame_bufs[i];
1951 for (int x=0;x<4;x++) {
1952 if (current->data[x]) {
1953 av_free(current->data[x]);
1958 all_frame_bufs.clear();
1959 free_frame_bufs.clear();
1960 locked_libav_frame_buf.clear();
1961 locked_uploading_frame_buf.clear();
1963 vpe_framebuf_mutex.Unlock();
1968 OsdOpenGL* osd=(OsdOpenGL*)osd->getInstance();
1969 osd->BeginPainting(); // get OpenGl context
1970 moco_shader->deinit();
1984 VPE_FrameBuf *VideoVPEOGL::getFrameBuf(unsigned int *size)
1986 VPE_FrameBuf* current=NULL;
1987 vpe_framebuf_mutex.Lock();
1988 if (free_frame_bufs.size()>0) {
1989 current=free_frame_bufs.front();
1990 free_frame_bufs.pop_front();
1991 } else if (all_frame_bufs.size()<6) {
1992 current=(VPE_FrameBuf*)malloc(sizeof(VPE_FrameBuf));
1993 memset(current,0,sizeof(VPE_FrameBuf));
1995 Log::getInstance()->log("Video", Log::NOTICE, "Framebuffer underrun!");
1996 vpe_framebuf_mutex.Unlock();
1997 return NULL; // We do not have a frame buffer
1999 locked_libav_frame_buf.push_back(current);
2000 vpe_framebuf_mutex.Unlock();
2001 //check if we need reallocation
2002 for (int x=0;x<4;x++) {
2003 if (current->size[x]!=size[x]) {
2004 current->data[x]=av_realloc(current->data[x],size[x]);
2005 current->size[x]=size[x];
2008 framebuf_framenum++;
2009 current->pict_num=framebuf_framenum; //This is used for tracking reference frames through the conversion pipeline
2014 void VideoVPEOGL::lockFrameBufUpload(VPE_FrameBuf* buf)
2016 // first find frame_buf memory
2018 //Log::getInstance()->log("Video", Log::NOTICE, "lock buffer upload %x",buf);
2019 VPE_FrameBuf* current=buf;
2020 vpe_framebuf_mutex.Lock();
2021 if (current) locked_uploading_frame_buf.push_back(current); //locked
2022 vpe_framebuf_mutex.Unlock();
2027 void VideoVPEOGL::releaseFrameBufLibav(VPE_FrameBuf* buf)
2029 // first find frame_buf memory
2030 //Log::getInstance()->log("Video", Log::NOTICE, "release buffer libav %x",buf);
2031 VPE_FrameBuf* current=buf;
2032 vpe_framebuf_mutex.Lock();
2034 locked_libav_frame_buf.remove(current); //unlocked
2035 list<VPE_FrameBuf*>::iterator itty=locked_uploading_frame_buf.begin();
2037 while (itty!=locked_uploading_frame_buf.end()) {
2038 if (*itty==current) {
2045 free_frame_bufs.push_back(current);
2048 vpe_framebuf_mutex.Unlock();
2051 void VideoVPEOGL::releaseFrameBufUpload(VPE_FrameBuf* buf)
2053 // first find frame_buf memory
2054 VPE_FrameBuf* current=buf;
2055 //Log::getInstance()->log("Video", Log::NOTICE, "release buffer upload %x",buf);
2056 vpe_framebuf_mutex.Lock();
2058 locked_uploading_frame_buf.remove(current); //unlocked
2059 list<VPE_FrameBuf*>::iterator itty=locked_libav_frame_buf.begin();
2061 while (itty!=locked_libav_frame_buf.end()) {
2062 if (*itty==current) {
2069 free_frame_bufs.push_back(current);
2072 vpe_framebuf_mutex.Unlock();
2075 void VideoVPEOGL::add_dec_frame_upload_only(struct AVCodecContext *s,const AVFrame* data)
2077 dec_frame_libav_mutex.Lock();
2078 libavwidth=s->width;
2079 libavheight=s->height;
2080 libavpixfmt=s->pix_fmt;
2081 //Log::getInstance()->log("Video", Log::DEBUG, "add_dec Frame info %d %d %d %d %x",libavwidth,libavheight,libavpixfmt,((VPE_FrameBuf*)data->base[0])->pict_num,data->base[0]);
2083 dec_frame_libav_upload_only_pending.push_back((VPE_FrameBuf*)data->base[0]); // we are only uploading
2084 dec_frame_libav_mutex.Unlock();
2094 int VideoVPEOGL::stop()
2096 if (!initted) return 0;
2098 #ifdef VPE_OMX_SUPPORT
2099 //Check if libav mode
2100 if (decoding_backend==VPE_DECODER_OMX) DeAllocateCodecsOMX();
2107 // if (ioctl(fdVideo, AV_SET_VID_STOP, 0) != 0) return 0;
2111 int VideoVPEOGL::reset()
2113 if (!initted) return 0;
2115 // if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0;
2119 int VideoVPEOGL::pause()
2121 if (!initted) return 0;
2123 // if (ioctl(fdVideo, AV_SET_VID_PAUSE, 0) != 0) return 0;
2127 int VideoVPEOGL::unPause() // FIXME get rid - same as play!!
2129 if (!initted) return 0;
2130 // if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
2134 int VideoVPEOGL::fastForward()
2136 if (!initted) return 0;
2138 // if (ioctl(fdVideo, AV_SET_VID_libavWD, 1) != 0) return 0;
2142 int VideoVPEOGL::unFastForward()
2144 if (!initted) return 0;
2146 // if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; // don't need this.
2148 //// if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
2152 int VideoVPEOGL::attachFrameBuffer()
2154 if (!initted) return 0;
2156 // if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
2160 int VideoVPEOGL::blank(void)
2162 // if (ioctl(fdVideo, AV_SET_VID_FB, 1) != 0) return 0;
2163 // if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
2167 ULLONG VideoVPEOGL::getCurrentTimestamp()
2169 /* sync_data_t timestamps;
2170 if (ioctl(fdVideo, AV_GET_VID_TIMESTAMPS, ×tamps) == 0)
2172 // FIXME are these the right way around?
2174 timestamps.stc = (timestamps.stc >> 31 ) | (timestamps.stc & 1);
2175 timestamps.pts = (timestamps.pts >> 31 ) | (timestamps.pts & 1);
2177 return timestamps.stc;
2186 ULONG VideoVPEOGL::timecodeToFrameNumber(ULLONG timecode)
2188 if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
2189 else return (ULONG)(((double)timecode / (double)90000) * (double)30);
2193 int VideoVPEOGL::test()
2198 // return ioctl(fdVideo, AV_SET_VID_STC, &stc);
2205 int VideoVPEOGL::test2()
2211 void VideoVPEOGL::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
2213 mediapacket = mplist.front();
2216 UINT VideoVPEOGL::DeliverMediaSample(UCHAR* buffer, UINT *samplepos)
2218 DeliverMediaPacket(mediapacket, buffer, samplepos);
2219 if (*samplepos == mediapacket.length) {
2226 UINT VideoVPEOGL::DeliverMediaPacket(MediaPacket packet,
2227 const UCHAR* buffer,
2230 if (packet.type == MPTYPE_VIDEO_H264)
2238 switch (decoding_backend) {
2239 default: case 0: return 0; // no backend runnigng
2240 #ifdef VPE_OMX_SUPPORT
2241 case VPE_DECODER_OMX: return DeliverMediaPacketOMX(packet,buffer,samplepos);
2243 #ifdef VPE_LIBAV_SUPPORT
2244 case VPE_DECODER_libav: return DeliverMediaPacketlibav(packet,buffer,samplepos);
2249 #ifdef VPE_OMX_SUPPORT
2250 UINT VideoVPEOGL::DeliverMediaPacketOMX(MediaPacket packet,
2251 const UCHAR* buffer,
2256 //Later add fail back code for libav
2258 *samplepos+=packet.length;
2259 return packet.length;
2263 if (!omx_running) return 0; // if we are not runnig do not do this
2266 OMX_ERRORTYPE error;
2268 /* OMX_PARAM_PORTDEFINITIONTYPE port_image;
2269 memset(&port_image,0,sizeof(port_image));
2270 port_image.nSize=sizeof(port_image);
2271 port_image.nVersion.nVersion=OMX_VERSION;
2272 port_image.nPortIndex =omx_codec_output_port;
2273 error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_image);
2274 if (error!= OMX_ErrorNone){
2275 Log::getInstance()->log("Video", Log::DEBUG, "OMX_GetParameter failed %x", error);
2277 Log::getInstance()->log("Video", Log::DEBUG, "Image port %d %d", port_image.format.video.nFrameWidth , port_image.format.video.nFrameHeight);*/
2279 /*First Check, if we have an audio sample*/
2283 return 0; //Not in iframe mode!
2287 if (packet.disconti) {
2289 if (cur_input_buf_omx) {
2290 OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx);
2291 if (error!=OMX_ErrorNone){
2292 Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error);
2294 cur_input_buf_omx=NULL;
2298 /*Inspect PES-Header */
2300 // OMX_STATETYPE temp_state;
2301 // OMX_GetState(omx_vid_dec,&temp_state);
2303 if (*samplepos==0) {//stripheader
2304 headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
2305 *samplepos+=headerstrip;
2306 if ( packet.synched ) {
2308 if (cur_input_buf_omx) {
2309 OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx);
2310 if (error!=OMX_ErrorNone){
2311 Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error);
2314 cur_input_buf_omx=NULL;//write out old data
2316 // reftime1=packet.presentation_time;
2317 // reftime2=reftime1+1;
2320 if (!firstsynched) {//
2321 *samplepos=packet.length;//if we have not processed at least one
2322 return packet.length;//synched packet ignore it!
2327 if (!cur_input_buf_omx) {
2328 input_bufs_omx_mutex.Lock();
2329 if (input_bufs_omx_free.size()==0) {
2330 input_bufs_omx_mutex.Unlock();
2331 Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket no free sample");
2332 return 0; // we do not have a free media sample
2335 cur_input_buf_omx=input_bufs_omx_free.front();
2336 cur_input_buf_omx->nFilledLen=0;
2337 cur_input_buf_omx->nOffset=0;
2338 cur_input_buf_omx->nTimeStamp=0;
2339 input_bufs_omx_free.pop_front();
2340 input_bufs_omx_mutex.Unlock();
2346 if (cur_input_buf_omx->nFilledLen==0) {//will only be changed on first packet
2347 /*if (packet.disconti) {
2348 ms->SetDiscontinuity(TRUE);
2350 ms->SetDiscontinuity(FALSE);
2352 //if (packet.synched) {
2354 //lastreftimePTS=packet.pts;
2355 if (omx_first_frame) { // TODO time
2356 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_STARTTIME;
2357 omx_first_frame=false;
2363 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
2366 // ms->SetSyncPoint(TRUE);
2370 unsigned int haveToCopy=packet.length-*samplepos;
2372 while (haveToCopy> (cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen)) {
2373 unsigned int cancopy=cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen;
2374 memcpy(cur_input_buf_omx->pBuffer+cur_input_buf_omx->nFilledLen,buffer+packet.pos_buffer+*samplepos,cancopy);
2375 haveToCopy-=cancopy;
2376 cur_input_buf_omx->nFilledLen+=cancopy;
2377 *samplepos+=cancopy;
2378 // push old buffer out
2380 OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx);
2381 if (error!=OMX_ErrorNone){
2382 Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error);
2385 input_bufs_omx_mutex.Lock();
2386 if (input_bufs_omx_free.size()==0) {
2387 input_bufs_omx_mutex.Unlock();
2388 //Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket no free sample");
2389 return *samplepos; // we do not have a free media sample
2391 cur_input_buf_omx=input_bufs_omx_free.front();
2392 cur_input_buf_omx->nFilledLen=0;
2393 cur_input_buf_omx->nOffset=0;
2394 cur_input_buf_omx->nTimeStamp=0;
2395 input_bufs_omx_free.pop_front();
2396 input_bufs_omx_mutex.Unlock();
2398 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
2401 memcpy(cur_input_buf_omx->pBuffer+cur_input_buf_omx->nFilledLen,
2402 buffer+packet.pos_buffer+*samplepos,haveToCopy);
2403 cur_input_buf_omx->nFilledLen+=haveToCopy;
2407 *samplepos+=haveToCopy;
2416 #ifdef VPE_LIBAV_SUPPORT
2417 int VideoVPEOGL::DecodePacketlibav()
2419 unsigned int haveToCopy=incom_packet_libav.size;
2420 if (incom_packet_libav.size==0) return 1; // we are already empty
2421 while (haveToCopy>0) {
2425 // Log::getInstance()->log("Video", Log::DEBUG, "Push data to decoder");
2427 #ifdef BENCHMARK_FPS
2428 int cur_time=getTimeMS();
2430 dec_bytes=avcodec_decode_video2(mpeg2codec_context_libav, dec_frame_libav_decoding,
2431 &frame_ready, &incom_packet_libav);
2432 #ifdef BENCHMARK_FPS
2433 time_in_decoder+=getTimeMS()-cur_time;
2434 if (frame_ready) num_frames++;
2435 if ((num_frames%100)==0) {
2436 float fps=1000./(float)(time_in_decoder);
2437 fps*=((float)num_frames);
2438 Log::getInstance()->log("Video", Log::NOTICE, "Current Pure Decoding FPS %g", fps);
2442 Log::getInstance()->log("Video", Log::DEBUG, "Decoding frame failed %x", dec_bytes);
2445 haveToCopy-=dec_bytes;
2447 // Log::getInstance()->log("Video", Log::DEBUG, "We have a frame push it to osd");
2449 lockFrameBufUpload((VPE_FrameBuf*)dec_frame_libav_decoding->base[0]); //lock for upload, so that ffmpeg does not reuse
2450 dec_frame_libav_mutex.Lock();
2451 libavwidth=mpeg2codec_context_libav->width;
2452 libavheight=mpeg2codec_context_libav->height;
2453 libavpixfmt=mpeg2codec_context_libav->pix_fmt;
2454 // Log::getInstance()->log("Video", Log::DEBUG, "Frame info %d %d %d",libavwidth,libavheight,libavpixfmt);
2455 // Log::getInstance()->log("Video", Log::DEBUG, "Frame info %d %d %d %d %x",libavwidth,libavheight,libavpixfmt,
2456 // ((VPE_FrameBuf*)dec_frame_libav_decoding->base[0])->pict_num,dec_frame_libav_decoding->base[0]);
2459 dec_frame_libav_upload_and_view_pending.push_back(dec_frame_libav_decoding);
2460 dec_frame_libav_decoding=NULL;
2461 if (dec_frame_libav_free.size()>0) {
2462 dec_frame_libav_decoding=dec_frame_libav_free.front();
2463 dec_frame_libav_free.pop_front();
2464 dec_frame_libav_mutex.Unlock();
2466 libav_hastime=false;
2468 libav_hastime=false;
2469 dec_frame_libav_mutex.Unlock();
2470 Log::getInstance()->log("Video", Log::DEBUG, "We have no free buffers 2 FPS");
2480 incom_packet_libav.size=0;
2486 UINT VideoVPEOGL::DeliverMediaPacketlibav(MediaPacket packet,
2487 const UCHAR* buffer,
2490 //Later add fail back code for libav
2492 *samplepos+=packet.length;
2493 return packet.length;
2496 if (!libav_running) return 0; // if we are not runnig do not do this
2502 return 0; //Not in iframe mode!
2506 if (packet.disconti) {
2508 if (!DecodePacketlibav()) return 0;
2511 /*Inspect PES-Header */
2512 if (!dec_frame_libav_decoding) {
2513 dec_frame_libav_mutex.Lock();
2514 if (dec_frame_libav_free.size()>0) {
2515 dec_frame_libav_decoding=dec_frame_libav_free.front();
2516 dec_frame_libav_free.pop_front();
2517 dec_frame_libav_mutex.Unlock();
2519 Log::getInstance()->log("Video", Log::DEBUG, "We have no free buffers FPS");
2520 dec_frame_libav_mutex.Unlock();
2528 if (*samplepos==0) {//stripheader
2529 headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
2530 *samplepos+=headerstrip;
2531 if ( packet.synched ) {
2533 if (!DecodePacketlibav()) return 0; // WriteOut old Data
2535 libav_time=packet.presentation_time;
2537 // reftime1=packet.presentation_time;
2538 // reftime2=reftime1+1;
2541 if (!firstsynched) {//
2542 *samplepos=packet.length;//if we have not processed at least one
2543 return packet.length;//synched packet ignore it!
2553 /*if (cur_input_buf_omx->nFilledLen==0) {//will only be changed on first packet
2554 /*if (packet.disconti) {
2555 ms->SetDiscontinuity(TRUE);
2557 ms->SetDiscontinuity(FALSE);
2559 //if (packet.synched) {
2561 //lastreftimePTS=packet.pts;
2562 if (omx_first_frame) { // TODO time
2563 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_STARTTIME;
2564 omx_first_frame=false;
2570 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
2573 // ms->SetSyncPoint(TRUE);
2577 unsigned int haveToCopy=packet.length-*samplepos;
2579 if ((incom_packet_libav_size-incom_packet_libav.size)< haveToCopy) {
2580 // if the buffer is to small reallocate
2581 incom_packet_libav_size+=haveToCopy;
2582 incom_packet_libav.data=(uint8_t*)av_realloc(incom_packet_libav.data,incom_packet_libav_size+FF_INPUT_BUFFER_PADDING_SIZE);
2583 Log::getInstance()->log("Video", Log::DEBUG, "Reallocate avpacket buffer to %d", incom_packet_libav_size);
2585 memcpy(incom_packet_libav.data+incom_packet_libav.size,buffer+packet.pos_buffer+*samplepos,haveToCopy);
2586 incom_packet_libav.size+=haveToCopy;
2588 *samplepos+=haveToCopy;
2603 void VideoVPEOGL::ResetTimeOffsets()
2607 bool VideoVPEOGL::displayIFrame(const UCHAR* buffer, UINT length)
2609 //write(fdVideo, buffer, length);
2610 if (!iframemode) EnterIframePlayback();
2611 // WriteOutTS(buffer,length, h264?MPTYPE_VIDEO_H264 :MPTYPE_VIDEO_MPEG2 );
2617 int VideoVPEOGL::EnterIframePlayback()