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;
71 VideoVPEOGL::~VideoVPEOGL()
76 int VideoVPEOGL::init(UCHAR tformat)
78 if (initted) return 0;
81 // if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
83 if (!setFormat(tformat)) { shutdown(); return 0; }
84 if (!setConnection(COMPOSITERGB)) { shutdown(); return 0; }
85 if (!setAspectRatio(ASPECT4X3)) { shutdown(); return 0; }
86 if (!setMode(NORMAL)) { shutdown(); return 0; }
87 if (!setSource()) { shutdown(); return 0; }
88 if (!attachFrameBuffer()) { shutdown(); return 0; }
92 /* if (format == PAL) setLetterboxBorder("38");
93 else setLetterboxBorder("31");*/
107 int VideoVPEOGL::initUsingOSDObjects()
109 EGLDisplay i_egl_display;
110 EGLSurface i_egl_surface;
111 EGLContext i_egl_context;
112 EGLConfig i_egl_config;
113 OsdOpenGL *osd=(OsdOpenGL*)osd->getInstance();
114 osd->getEGLObjs(&i_egl_display,&i_egl_surface,&i_egl_context, &i_egl_config);
115 const EGLint attr_context[]={
116 EGL_CONTEXT_CLIENT_VERSION,2,
120 egl_display=i_egl_display;
121 egl_context=eglCreateContext(egl_display,i_egl_config,i_egl_context,attr_context);
122 if (egl_context==EGL_NO_CONTEXT) {
123 Log::getInstance()->log("Video", Log::WARN, "Creating egl context failed! %x",eglGetError());
126 // We create a dummy surface here, in order to allow two contexts
127 const EGLint attr_pbuffer[]={
128 EGL_WIDTH, 1, EGL_HEIGHT,1,
131 egl_surface=eglCreatePbufferSurface(egl_display,i_egl_config,attr_pbuffer);
132 if (egl_surface==EGL_NO_SURFACE) {
133 Log::getInstance()->log("Video", Log::WARN, "Creating egl pbuffer failed! %x",eglGetError());
140 //egl_surface=i_egl_surface;
141 //egl_context=i_egl_context;
144 #ifdef VPE_OMX_SUPPORT
145 // we are called before the audio
148 if (error!=OMX_ErrorNone) {
149 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX failed %x", error);
153 //our callbacks move to play?
157 #ifdef VPE_LIBAV_SUPPORT
160 if (decoding_mode==VPE_NO_XVMC) {
161 mpeg2codec_libav=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO);
163 mpeg2codec_libav=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO_XVMC);
165 if (mpeg2codec_libav==NULL) {
166 Log::getInstance()->log("Video", Log::DEBUG, "Find libav mpeg2 codec failed");
176 #ifdef VPE_OMX_SUPPORT
178 OMX_ERRORTYPE VideoVPEOGL::EventHandler_OMX(OMX_IN OMX_HANDLETYPE handle,OMX_IN OMX_PTR appdata,
179 OMX_IN OMX_EVENTTYPE event_type,OMX_IN OMX_U32 data1,
180 OMX_IN OMX_U32 data2,OMX_IN OMX_PTR event_data) {
182 Log::getInstance()->log("Video", Log::NOTICE, "eventHandler %x %x %x %x %x",handle,event_type,data1,data2,event_data);
184 struct VPE_OMX_EVENT new_event;
185 new_event.handle=handle;
186 new_event.appdata=appdata;
187 new_event.event_type=event_type;
188 new_event.data1=data1;
189 new_event.data2=data2;
190 new_event.event_data=event_data;
192 VideoVPEOGL *video=(VideoVPEOGL *)getInstance();
193 video->AddOmxEvent(new_event);
195 /* switch (event_type) {
196 case OMX_EventCmdComplete: {
201 return OMX_ErrorNone;
205 void VideoVPEOGL::AddOmxEvent(VPE_OMX_EVENT new_event)
207 omx_event_mutex.Lock();
208 omx_events.push_back(new_event);
209 omx_event_mutex.Unlock();
213 OMX_ERRORTYPE VideoVPEOGL::EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer){
215 Log::getInstance()->log("Video", Log::NOTICE, "EmptyBufferDone");
216 VideoVPEOGL *video=(VideoVPEOGL *)getInstance();
217 video->ReturnEmptyOMXBuffer(buffer);
218 return OMX_ErrorNone;
222 void VideoVPEOGL::ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer){
223 input_bufs_omx_mutex.Lock();
224 Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size());
225 input_bufs_omx_free.push_back(buffer);
226 Log::getInstance()->log("Video", Log::NOTICE, "ReturnEmptyOMXBuffer %d",input_bufs_omx_free.size());
227 input_bufs_omx_mutex.Unlock();
230 OMX_ERRORTYPE VideoVPEOGL::FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer) {
231 Log::getInstance()->log("Video", Log::NOTICE, "FillBufferDone");
232 return OMX_ErrorNone;
237 int VideoVPEOGL::shutdown()
239 if (!initted) return 0;
244 #ifdef VPE_OMX_SUPPORT
245 DeAllocateCodecsOMX();
248 #ifdef VPE_LIBAV_SUPPORT
249 DeAllocateCodecsLibav();
251 eglDestroyContext(egl_display,egl_context);
256 int VideoVPEOGL::AllocateYUV400OglTexture(VPEOGLFrame* outframe,int width,int height,int stride)
258 Log::getInstance()->log("Video", Log::NOTICE, "Allocate ogl texture 400");
260 glGenTextures(1, &outframe->textures[0]);
261 glBindTexture(GL_TEXTURE_2D, outframe->textures[0]);
262 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, stride, height, 0, GL_LUMINANCE,
263 GL_UNSIGNED_BYTE, NULL);
265 glGenTextures(1, &outframe->textures[1]);
266 glBindTexture(GL_TEXTURE_2D, outframe->textures[1]);
267 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, stride>>1, height>>1, 0, GL_LUMINANCE,
268 GL_UNSIGNED_BYTE, NULL);
270 glGenTextures(1, &outframe->textures[2]);
271 glBindTexture(GL_TEXTURE_2D, outframe->textures[2]);
272 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, stride>>1, height>>1, 0, GL_LUMINANCE,
273 GL_UNSIGNED_BYTE, NULL);
274 outframe->height=height;
275 outframe->width=width;
276 outframe->stride=stride;
281 int VideoVPEOGL::AllocateYUV444OglTexture(VPEOGLFrame* outframe,int width,int height,int stride)
283 Log::getInstance()->log("Video", Log::NOTICE, "Allocate ogl texture 444");
285 glGenTextures(1, &outframe->textures[0]);
286 glBindTexture(GL_TEXTURE_2D, outframe->textures[0]);
287 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
288 GL_UNSIGNED_BYTE, NULL);
289 outframe->textures[1]=outframe->textures[2]=0; // no handles here
295 outframe->height=height;
296 outframe->width=width;
297 outframe->stride=stride;// does not make any sense otherwise, just to prevent reallocating
302 VPEOGLFrame *VideoVPEOGL::getReadyOGLFrame(){
303 VPEOGLFrame *return_obj=NULL;
304 ogl_frame_mutex.Lock();
305 if (ready_ogl_frames.size()>0) {
306 return_obj=ready_ogl_frames.front();
307 ready_ogl_frames.pop_front();
308 //Log::getInstance()->log("Video", Log::WARN, "readyOGLRFrame markoutgoing num: %d",return_obj->pict_num);
309 ogl_frame_outside=true;
311 ogl_frame_mutex.Unlock();
315 void VideoVPEOGL::returnOGLFrame(VPEOGLFrame *frame)
317 ogl_frame_mutex.Lock();
319 ogl_frame_outside=false;
320 //Log::getInstance()->log("Video", Log::WARN, "returnOGLRFrame mark incoming num: %d",frame->pict_num);
321 if (frame->pict_num==ogl_forward_ref_frame_num ||
322 frame->pict_num==ogl_backward_ref_frame_num ) {
323 recycle_ref_ogl_frames.push_back(frame);
325 free_ogl_frames.push_back(frame);
328 ogl_frame_mutex.Unlock();
331 void VideoVPEOGL::recycleOGLRefFrames()
333 // This function recycles frames formerly used as reference frame
334 ogl_frame_mutex.Lock();
335 list<VPEOGLFrame*> keep;
336 list<VPEOGLFrame*>::iterator itty=recycle_ref_ogl_frames.begin();
337 while (itty!=recycle_ref_ogl_frames.end()) {
338 // Log::getInstance()->log("Video", Log::WARN, "recycleOGLRefFrame mark3");
339 if ((*itty)->pict_num==ogl_forward_ref_frame_num
340 || (*itty)->pict_num==ogl_backward_ref_frame_num)
342 // ok we have to keep this
343 keep.push_back(*itty);
345 free_ogl_frames.push_back(*itty);
349 recycle_ref_ogl_frames.clear();
350 recycle_ref_ogl_frames=keep;
352 ogl_frame_mutex.Unlock();
357 void VideoVPEOGL::threadMethod()
359 if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {
360 Log::getInstance()->log("Video", Log::WARN, "Making egl Current failed in thread %d",eglGetError());
369 #ifdef VPE_LIBAV_SUPPORT
370 dec_frame_libav_mutex.Lock();
371 AVFrame* dec_frame_libav_uploading_int=NULL;
374 if (dec_frame_libav_upload_and_view_pending.size()>0 ) {
376 dec_frame_libav_uploading_int=dec_frame_libav_upload_and_view_pending.front();
377 dec_frame_libav_uploading_framebuf=(VPE_FrameBuf*)dec_frame_libav_uploading_int->base[0];
378 // Log::getInstance()->log("Video", Log::WARN, "threadMethod u and view %d %lld %x",(dec_frame_libav_uploading_framebuf)->pict_num,run,
379 // dec_frame_libav_uploading_framebuf);
380 // if (dec_frame_libav_upload_only_pending.size()>0) Log::getInstance()->log("Video", Log::WARN, "threadMethod u and view2 %d",
381 // ((VPE_FrameBuf*)dec_frame_libav_upload_only_pending.front())->pict_num);
384 if ((dec_frame_libav_uploading_framebuf)->ogl_uploaded || decoding_mode==VPE_NO_XVMC ) {
385 dec_frame_libav_upload_and_view_pending.pop_front();
386 if (decoding_mode==VPE_NO_XVMC) upload=true;
388 dec_frame_libav_uploading_framebuf=NULL;
389 dec_frame_libav_uploading_int=NULL; // if not uploaded do not do it yet
390 view=false; //do the upload
391 // Log::getInstance()->log("Video", Log::WARN, "threadMethod u and view view canceled");
395 if (!view && dec_frame_libav_upload_only_pending.size()>0) { //this is for uploading reference frames ahead
397 dec_frame_libav_uploading_framebuf=dec_frame_libav_upload_only_pending.front();
398 // Log::getInstance()->log("Video", Log::WARN, "threadMethod u %d %lld %x",((VPE_FrameBuf*)dec_frame_libav_uploading_framebuf)->pict_num,run,
399 // dec_frame_libav_uploading_framebuf);
400 dec_frame_libav_upload_only_pending.pop_front();
403 /* if (((VPE_FrameBuf*)dec_frame_libav_uploading->base[0])->ogl_uploaded) {
405 dec_frame_libav_uploading=NULL; //do not upload again
414 if (dec_frame_libav_upload_and_view_pending.size()>0
415 ||dec_frame_libav_upload_only_pending.size()>0) sleep=false;
417 dec_frame_libav_mutex.Unlock();
420 if (dec_frame_libav_uploading_framebuf) {
422 //Code Block for debugging if needed
423 /* Log::getInstance()->log("Video", Log::WARN, "Iterate all free ogl frames");
424 ogl_frame_mutex.Lock();
425 list<VPEOGLFrame*>::iterator itty=free_ogl_frames.begin();
426 while (itty!=free_ogl_frames.end()) {
427 Log::getInstance()->log("Video", Log::WARN, "free ogl pict num %d",(*itty)->pict_num);
432 itty=recycle_ref_ogl_frames.begin();
433 while (itty!=recycle_ref_ogl_frames.end()) {
434 Log::getInstance()->log("Video", Log::WARN, "recycle ogl pict num %d",(*itty)->pict_num);
438 itty=ready_ogl_frames.begin();
439 while (itty!=ready_ogl_frames.end()) {
440 Log::getInstance()->log("Video", Log::WARN, "ready ogl pict num %d",(*itty)->pict_num);
444 ogl_frame_mutex.Unlock();*/
448 int width,height,pixfmt;
449 //First get a free ogl image
450 VPEOGLFrame* out_frame=NULL;
453 ogl_frame_mutex.Lock();
454 // Log::getInstance()->log("Video", Log::WARN, "threadMethod mark upload 1a %d %d %d %d %d",all_ogl_frames.size(),free_ogl_frames.size(),
455 // recycle_ref_ogl_frames.size(),ready_ogl_frames.size(),ogl_frame_outside);
456 if (all_ogl_frames.size()==0) {
457 ogl_frame_mutex.Unlock(); break;
460 if (free_ogl_frames.size()>0) {
464 out_frame=free_ogl_frames.front();
465 free_ogl_frames.pop_front();
467 ogl_frame_mutex.Unlock();
470 ogl_frame_mutex.Lock();
472 // if (msleep)Log::getInstance()->log("Video", Log::WARN, "msleep FPS %d",msleep);
473 ogl_frame_mutex.Unlock();
477 // Log::getInstance()->log("Video", Log::WARN, "outframes old pict num: %d",out_frame->pict_num);
478 if (out_frame->textures[0]==0 || out_frame->width!=width ||
479 out_frame->height!=height || out_frame->stride!=dec_frame_libav_uploading_framebuf->stride) {
480 if (out_frame->textures[0]!=0) {
481 glDeleteTextures(1,&out_frame->textures[0]);
482 out_frame->textures[0]=0;
484 if (out_frame->textures[1]!=0) {
485 glDeleteTextures(1,&out_frame->textures[1]);
486 out_frame->textures[1]=0;
488 if (out_frame->textures[2]!=0) {
489 glDeleteTextures(1,&out_frame->textures[2]);
490 out_frame->textures[2]=0;
493 if (decoding_mode==VPE_NO_XVMC) {
494 if (!AllocateYUV400OglTexture(out_frame,width,height,dec_frame_libav_uploading_framebuf->stride)) failed=true;
496 if (!AllocateYUV444OglTexture(out_frame,width,height,dec_frame_libav_uploading_framebuf->stride)) failed=true; //We use a YUV 444 texture in this case
497 // the shaders are easier to implement
500 dec_frame_libav_uploading_framebuf->ogl_ref=out_frame;
501 dec_frame_libav_uploading_framebuf->ogl_uploaded=true;
505 //up to now only YUV data, this is for reference only, since the pi is too slow.
506 if (decoding_mode==VPE_NO_XVMC) {
507 glBindTexture(GL_TEXTURE_2D, out_frame->textures[0]);
508 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
509 glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
510 out_frame->stride,out_frame->height,
511 GL_LUMINANCE,GL_UNSIGNED_BYTE,
512 dec_frame_libav_uploading_framebuf->data[0]);
514 glBindTexture(GL_TEXTURE_2D, out_frame->textures[1]);
515 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
516 glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
517 out_frame->stride>>1,out_frame->height>>1,
518 GL_LUMINANCE,GL_UNSIGNED_BYTE,
519 dec_frame_libav_uploading_framebuf->data[1]);
521 glBindTexture(GL_TEXTURE_2D, out_frame->textures[2]);
522 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
523 glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
524 out_frame->stride>>1,out_frame->height>>1,
525 GL_LUMINANCE,GL_UNSIGNED_BYTE,
526 dec_frame_libav_uploading_framebuf->data[2]);
529 // Log::getInstance()->log("Video", Log::WARN, "XVMC mark1");
530 xvmc_pix_fmt * pix_fmt=(xvmc_pix_fmt *)dec_frame_libav_uploading_framebuf->data[2];
531 if (moco_shader && pix_fmt) {
534 int cur_time=getTimeMS();
536 moco_shader->uploadDataBlocks(pix_fmt->data_blocks,pix_fmt->next_free_data_block_num,
537 pix_fmt->mv_blocks , pix_fmt->filled_mv_blocks_num );
538 // Log::getInstance()->log("Video", Log::WARN, "Pictnum %d Forward %d Backward %d ",pix_fmt->p_surface,
539 // pix_fmt->p_past_surface,pix_fmt->p_future_surface);
541 if (((int)pix_fmt->p_future_surface)!=0 && ogl_backward_ref_frame_num!=((int)pix_fmt->p_future_surface))
543 //Now determine the frame, that fits
544 ogl_frame_mutex.Lock();
546 for (int i=0;i<all_ogl_frames.size();i++) {
547 if (all_ogl_frames[i]->pict_num==((int)pix_fmt->p_future_surface))
549 ogl_forward_ref_frame=ogl_backward_ref_frame; //mpeg life time axioms
550 ogl_forward_ref_frame_num=ogl_backward_ref_frame_num;
551 ogl_backward_ref_frame=all_ogl_frames[i];
552 ogl_backward_ref_frame_num=(int)pix_fmt->p_future_surface;
557 // if (!found) {// for debugging
558 // Log::getInstance()->log("Video", Log::WARN, "Emergency reference frame not found");
562 ogl_frame_mutex.Unlock();
563 recycleOGLRefFrames(); //needed for recycling of reference frames
565 // Log::getInstance()->log("Video", Log::WARN, "Pictnum mark1");
568 if ( ((int)pix_fmt->p_past_surface)==ogl_backward_ref_frame_num)
573 if (((int)pix_fmt->p_past_surface)!=0 && ogl_forward_ref_frame_num!=((int)pix_fmt->p_past_surface))
575 //Now determine the frame, that fits
576 ogl_frame_mutex.Lock();
578 for (int i=0;i<all_ogl_frames.size();i++) {
579 if (all_ogl_frames[i]->pict_num==((int)pix_fmt->p_past_surface))
581 ogl_forward_ref_frame=all_ogl_frames[i];
582 ogl_forward_ref_frame_num=(int)pix_fmt->p_past_surface; // This should not happen, or for DMV, who knows
588 // Log::getInstance()->log("Video", Log::WARN, "Emergency reference frame not found %d %d",ogl_forward_ref_frame_num,
589 // ((int)pix_fmt->p_past_surface));
593 ogl_frame_mutex.Unlock();
594 recycleOGLRefFrames(); //needed for recycling of reference frames
597 //Log::getInstance()->log("Video", Log::WARN, "Pictnum mark2");
599 if (decoding_mode==VPE_XVMC_MOCOMP)
606 out_frame->pict_num=dec_frame_libav_uploading_framebuf->pict_num;
608 // Log::getInstance()->log("Video", Log::WARN, "Pictnum mark3");
610 moco_shader->doMoCo(out_frame,(((int)pix_fmt->p_past_surface)!=0)? ogl_forward_ref_frame:NULL,
611 (((int)pix_fmt->p_future_surface)!=0)? ogl_backward_ref_frame:NULL);
614 time_in_decoder_gl+=getTimeMS()-cur_time;
616 if ((num_frames_gl%100)==0) {
617 float fps=1000./(float)(time_in_decoder_gl);
618 fps*=((float)num_frames_gl);
619 Log::getInstance()->log("Video", Log::NOTICE, "Current GL Decoding FPS %g", fps);
623 //Log::getInstance()->log("Video", Log::WARN, "Pictnum mark4");
624 // Excute motion compensation
626 //Log::getInstance()->log("Video", Log::WARN, "moco pixfmt error abort");
642 //Log::getInstance()->log("Video", Log::WARN, "threadMethod mark view");
643 VPEOGLFrame* out_frame=dec_frame_libav_uploading_framebuf->ogl_ref;
644 xvmc_pix_fmt * pix_fmt=(xvmc_pix_fmt *)dec_frame_libav_uploading_framebuf->data[2];
645 /* Log::getInstance()->log("Video", Log::WARN, "View Pictnum %d Forward %d Backward %d pict_num %d",pix_fmt->p_surface,
646 pix_fmt->p_past_surface,pix_fmt->p_future_surface,out_frame->pict_num);
647 Log::getInstance()->log("Video", Log::WARN, "Real Pictnum %d ",out_frame->pict_num);*/
649 releaseFrameBufUpload(dec_frame_libav_uploading_framebuf);
650 ogl_frame_mutex.Lock();
651 ready_ogl_frames.push_back(out_frame);
652 ogl_frame_mutex.Unlock();
653 ((OsdOpenGL*)Osd::getInstance())->AdviseAboutNewFrame(); //Tell him, that we have a frame waiting
655 dec_frame_libav_mutex.Lock();
656 dec_frame_libav_free.push_back(dec_frame_libav_uploading_int);
657 dec_frame_libav_mutex.Unlock();
661 dec_frame_libav_mutex.Lock();
662 dec_frame_libav_uploading_framebuf=NULL;
664 if (dec_frame_libav_upload_and_view_pending.size()>0
665 ||dec_frame_libav_upload_only_pending.size()>0) sleep=false;
667 dec_frame_libav_mutex.Unlock();
675 struct timespec target_time;
677 clock_gettime(CLOCK_REALTIME,&target_time);
678 target_time.tv_nsec+=1000000LL*ts;
679 if (target_time.tv_nsec>999999999) {
680 target_time.tv_nsec-=1000000000L;
681 target_time.tv_sec+=1;
683 threadWaitForSignalTimed(&target_time);
684 //Log::getInstance()->log("Video", Log::WARN, "threadMethod signalled FPS");
692 void VideoVPEOGL::threadPostStopCleanup()
694 eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
695 #ifdef VPE_LIBAV_SUPPORT
696 dec_frame_libav_uploading_framebuf=NULL;
703 int VideoVPEOGL::setTVsize(UCHAR ttvsize)
707 // Override the aspect ratio usage, temporarily use to set the video chip mode
708 if (!setAspectRatio(tvsize)) { shutdown(); return 0; }
710 if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
711 if (!setSource()) { shutdown(); return 0; }
712 if (!attachFramebuffer()) { shutdown(); return 0; }
714 // Reopening the fd causes the scart aspect line to go back to 4:3
715 // Set this again to the same as the tv screen size
716 if (!setAspectRatio(tvsize)) { shutdown(); return 0; }
718 // mode == LETTERBOX is invalid if the TV is widescreen
719 if (tvsize == ASPECT16X9) setMode(NORMAL);
724 int VideoVPEOGL::setDefaultAspect()
726 return setAspectRatio(tvsize);
731 int VideoVPEOGL::setFormat(UCHAR tformat)
733 if (!initted) return 0;
734 if ((tformat != PAL) && (tformat != NTSC)) return 0;
737 // if (ioctl(fdVideo, AV_SET_VID_DISP_FMT, format) != 0) return 0;
753 int VideoVPEOGL::setConnection(UCHAR tconnection)
755 if (!initted) return 0;
756 if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;
757 connection = tconnection;
759 // if (ioctl(fdVideo, AV_SET_VID_OUTPUT, connection) != 0) return 0;
763 int VideoVPEOGL::setAspectRatio(UCHAR taspectRatio)
765 if (!initted) return 0;
766 if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
767 aspectRatio = taspectRatio;
769 Log::getInstance()->log("Video", Log::DEBUG, "Setting aspect to %i", aspectRatio);
771 // if (ioctl(fdVideo, AV_SET_VID_RATIO, aspectRatio) != 0) return 0;
775 int VideoVPEOGL::setMode(UCHAR tmode)
777 if (!initted) return 0;
779 if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode
781 if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH)
782 && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0;
785 // if (ioctl(fdVideo, AV_SET_VID_MODE, mode) != 0) return 0;
789 int VideoVPEOGL::signalOff()
791 // if (ioctl(fdVideo, AV_SET_VID_DENC, 0) != 0) return 0;
795 int VideoVPEOGL::signalOn()
797 // if (ioctl(fdVideo, AV_SET_VID_DENC, 1) != 0) return 0;
801 int VideoVPEOGL::setSource()
803 if (!initted) return 0;
805 // What does this do...
806 // if (ioctl(fdVideo, AV_SET_VID_SRC, 1) != 0) return 0;
810 int VideoVPEOGL::setPosition(int x, int y)
812 if (!initted) return 0;
814 // vid_pos_regs_t pos_d;
818 /* vid_pos_regs_t pos_d;
820 memset(&pos_d, 0, sizeof(pos_d));
845 pos_d.y = 100; // Top left X
846 pos_d.x = 50; // Top left Y
854 // if (ioctl(fdVideo, AV_SET_VID_POSITION, &pos_d) != 0) return 0;
858 int VideoVPEOGL::sync()
860 if (!initted) return 0;
862 // if (ioctl(fdVideo, AV_SET_VID_SYNC, 2) != 0) return 0;
869 int VideoVPEOGL::play()
871 if (!initted) return 0;
873 #ifdef VPE_OMX_SUPPORT
876 if (!omx_h264) doomx=false;
878 if (!omx_mpeg2) doomx=false;
881 if (AllocateCodecsOMX()) {
882 decoding_backend=VPE_DECODER_OMX;
884 // Otherwise fall back to libav
888 Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX failed assume h264 unsupported");
891 Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX failed assume mpeg2 unsupported");
896 #ifdef VPE_LIBAV_SUPPORT
897 if (AllocateCodecsLibav()) {
898 decoding_backend=VPE_DECODER_libav;
900 // Otherwise fall back to libav
909 #ifdef VPE_OMX_SUPPORT
910 int VideoVPEOGL::AllocateCodecsOMX()
913 static OMX_CALLBACKTYPE callbacks= {&EventHandler_OMX,&EmptyBufferDone_OMX,&FillBufferDone_OMX};
915 Log::getInstance()->log("Video", Log::NOTICE, "Allocate Codecs OMX");
916 //Clock, move later to audio
920 error=OMX_GetHandle(&omx_clock,VPE_OMX_CLOCK,NULL,&callbacks);
923 if (error!=OMX_ErrorNone){
924 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX clock failed %x", error);
925 DeAllocateCodecsOMX();
931 OMX_PORT_PARAM_TYPE p_param;
932 memset(&p_param,0,sizeof(p_param));
933 p_param.nSize=sizeof(p_param);
934 p_param.nVersion.nVersion=OMX_VERSION;
935 error=OMX_GetParameter(omx_clock,OMX_IndexParamOtherInit,&p_param);
936 if (error!=OMX_ErrorNone){
937 Log::getInstance()->log("Video", Log::DEBUG, "Init clock OMX_GetParameter failed %x", error);
938 DeAllocateCodecsOMX();
941 omx_clock_output_port=p_param.nStartPortNumber;
943 for (unsigned int i=0;i<p_param.nPorts;i++) {
944 if (!DisablePort(omx_clock,p_param.nStartPortNumber+i) ) {
945 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX clock failed %d",i);
946 DeAllocateCodecsOMX();
952 OMX_TIME_CONFIG_CLOCKSTATETYPE clock_conf;
953 memset(&clock_conf,0,sizeof(clock_conf));
954 clock_conf.nSize=sizeof(clock_conf);
955 clock_conf.nVersion.nVersion=OMX_VERSION;
956 clock_conf.eState=OMX_TIME_ClockStateWaitingForStartTime;
957 clock_conf.nStartTime=0;
958 clock_conf.nOffset=0;
959 clock_conf.nWaitMask=OMX_CLOCKPORT0;
960 error=OMX_SetParameter(omx_clock,OMX_IndexConfigTimeClockState,&clock_conf);
961 if (error!=OMX_ErrorNone){
962 Log::getInstance()->log("Video", Log::DEBUG, "Clock IndexConfigTimeClockState failed %x", error);
963 DeAllocateCodecsOMX();
970 error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_H264_DECODER,NULL,&callbacks);
972 error=OMX_GetHandle(&omx_vid_dec,VPE_OMX_MPEG2_DECODER,NULL,&callbacks);
975 if (error!=OMX_ErrorNone){
976 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video decoder failed %x", error);
977 DeAllocateCodecsOMX();
983 memset(&p_param,0,sizeof(p_param));
984 p_param.nSize=sizeof(p_param);
985 p_param.nVersion.nVersion=OMX_VERSION;
986 error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamVideoInit,&p_param);
987 if (error!=OMX_ErrorNone){
988 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX h264 decoder OMX_GetParameter failed %x", error);
989 DeAllocateCodecsOMX();
992 omx_codec_input_port=p_param.nStartPortNumber;
993 omx_codec_output_port=p_param.nStartPortNumber+1;
995 if (!DisablePort(omx_vid_dec,omx_codec_input_port) || !DisablePort(omx_vid_dec,omx_codec_output_port)) {
996 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video decoder failed");
997 DeAllocateCodecsOMX();
1002 OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE conceal;
1003 memset(&conceal,0,sizeof(conceal));
1004 conceal.nSize=sizeof(conceal);
1005 conceal.nVersion.nVersion=OMX_VERSION;
1006 conceal.bStartWithValidFrame=OMX_FALSE;
1008 error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamBrcmVideoDecodeErrorConcealment,&conceal);
1009 if (error!=OMX_ErrorNone){
1010 Log::getInstance()->log("Video", Log::DEBUG, "OMX_IndexParamBrcmVideoDecodeErrorConcealment failed %x", error);
1011 DeAllocateCodecsOMX();
1016 error=OMX_GetHandle(&omx_vid_sched,VPE_OMX_VIDEO_SCHED,NULL,&callbacks);
1017 if (error!=OMX_ErrorNone){
1018 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler failed %x", error);
1019 DeAllocateCodecsOMX();
1025 error=OMX_GetParameter(omx_vid_sched,OMX_IndexParamVideoInit,&p_param);
1026 if (error!=OMX_ErrorNone){
1027 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler OMX_GetParameter failed %x", error);
1028 DeAllocateCodecsOMX();
1031 omx_shed_input_port=p_param.nStartPortNumber;
1032 omx_shed_output_port=p_param.nStartPortNumber+1;
1035 error=OMX_GetParameter(omx_vid_sched,OMX_IndexParamOtherInit,&p_param);
1036 if (error!=OMX_ErrorNone){
1037 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video scheduler OMX_GetParameter failed %x", error);
1038 DeAllocateCodecsOMX();
1041 omx_shed_clock_port=p_param.nStartPortNumber;
1044 if (!DisablePort(omx_vid_sched,omx_shed_input_port) || !DisablePort(omx_vid_sched,omx_shed_output_port)
1045 || !DisablePort(omx_vid_sched,omx_shed_clock_port)) {
1046 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video shed failed");
1047 DeAllocateCodecsOMX();
1052 error=OMX_GetHandle(&omx_vid_rend,VPE_OMX_VIDEO_REND,NULL,&callbacks);
1053 if (error!=OMX_ErrorNone){
1054 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video rend failed %x", error);
1055 DeAllocateCodecsOMX();
1059 error=OMX_GetParameter(omx_vid_rend,OMX_IndexParamVideoInit,&p_param);
1060 if (error!=OMX_ErrorNone){
1061 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX video rend OMX_GetParameter failed %x", error);
1062 DeAllocateCodecsOMX();
1065 omx_rend_input_port=p_param.nStartPortNumber;
1066 //omx_rend_output_port=p_param.nStartPortNumber+1;
1069 if (!DisablePort(omx_vid_rend,omx_rend_input_port) /*|| !DisablePort(omx_vid_rend,omx_rend_output_port)*/
1071 Log::getInstance()->log("Video", Log::DEBUG, "Disable Ports OMX video rend failed");
1072 DeAllocateCodecsOMX();
1085 /* error=OMX_SendCommand(omx_vid_dec,OMX_CommandStateSet,OMX_StateIdle,0);
1086 if (error!=OMX_ErrorNone){
1087 Log::getInstance()->log("Video", Log::DEBUG, "vid_dec Send Command to OMX State Idle %x", error);
1094 OMX_VIDEO_PARAM_PORTFORMATTYPE ft_type;
1095 memset(&ft_type,0,sizeof(ft_type));
1096 ft_type.nSize=sizeof(ft_type);
1097 ft_type.nVersion.nVersion=OMX_VERSION;
1099 ft_type.nPortIndex=omx_codec_input_port;
1101 ft_type.eCompressionFormat=OMX_VIDEO_CodingAVC;
1103 ft_type.eCompressionFormat=OMX_VIDEO_CodingMPEG2;
1106 Demuxer* demux=Demuxer::getInstance();
1108 ft_type.xFramerate=0;//25*(1<<16);//demux->getFrameRate()*(1<<16);
1109 Log::getInstance()->log("Video", Log::DEBUG, "Framerate: %d",demux->getFrameRate());
1110 error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamVideoPortFormat,&ft_type);
1111 if (error!=OMX_ErrorNone){
1112 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexParamVideoPortFormat failed %x", error);
1113 DeAllocateCodecsOMX();
1118 if (!ChangeComponentState(omx_vid_dec,OMX_StateIdle)) {
1119 Log::getInstance()->log("Video", Log::DEBUG, "vid_dec ChangeComponentState");
1120 DeAllocateCodecsOMX();
1125 if (!PrepareInputBufsOMX()) {
1126 DeAllocateCodecsOMX();
1131 if (!ChangeComponentState(omx_clock,OMX_StateIdle)) {
1132 Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Idle");
1133 DeAllocateCodecsOMX();
1137 error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,omx_vid_sched,omx_shed_clock_port);
1138 if (error!=OMX_ErrorNone){
1139 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);
1140 DeAllocateCodecsOMX();
1144 if (!EnablePort(omx_clock,omx_clock_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_clock_port,false)
1146 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX clock shed failed");
1147 DeAllocateCodecsOMX();
1151 if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_clock_port)) {
1152 DeAllocateCodecsOMX();
1156 error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,omx_vid_sched,omx_shed_input_port);
1157 if (error!=OMX_ErrorNone){
1158 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel dec to sched failed %x", error);
1159 DeAllocateCodecsOMX();
1165 if (!EnablePort(omx_vid_dec,omx_codec_output_port,false) || !EnablePort(omx_vid_sched,omx_shed_input_port,false)
1167 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX codec shed failed");
1168 DeAllocateCodecsOMX();
1172 if ( !CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_input_port)) {
1175 if (!ChangeComponentState(omx_vid_sched,OMX_StateIdle)) {
1176 Log::getInstance()->log("Video", Log::DEBUG, "vid_sched idle ChangeComponentState");
1177 DeAllocateCodecsOMX();
1180 if (!CommandFinished(omx_clock,OMX_CommandPortEnable,omx_clock_output_port)
1181 ||!CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_output_port)){
1182 DeAllocateCodecsOMX();
1186 if (!ChangeComponentState(omx_vid_dec,OMX_StateExecuting)) {
1187 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_dec ChangeComponentState Execute");
1188 DeAllocateCodecsOMX();
1192 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_output_port,omx_vid_rend,omx_rend_input_port);
1193 if (error!=OMX_ErrorNone){
1194 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel sched to rend failed %x", error);
1195 DeAllocateCodecsOMX();
1199 if (!EnablePort(omx_vid_sched,omx_shed_output_port,false) || !EnablePort(omx_vid_rend,omx_rend_input_port,false)
1201 Log::getInstance()->log("Video", Log::DEBUG, "Enable Ports OMX shed rend failed");
1202 DeAllocateCodecsOMX();
1206 if (!CommandFinished(omx_vid_sched,OMX_CommandPortEnable,omx_shed_output_port)
1207 || !CommandFinished(omx_vid_rend,OMX_CommandPortEnable,omx_rend_input_port)) {
1208 DeAllocateCodecsOMX();
1212 if (!ChangeComponentState(omx_vid_rend,OMX_StateIdle)) {
1213 Log::getInstance()->log("Video", Log::DEBUG, "vid_rend ChangeComponentState");
1214 DeAllocateCodecsOMX();
1219 if (!ChangeComponentState(omx_vid_sched,OMX_StateExecuting)) {
1220 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_sched ChangeComponentState Execute");
1221 DeAllocateCodecsOMX();
1225 if (!ChangeComponentState(omx_vid_rend,OMX_StateExecuting)) {
1226 Log::getInstance()->log("Video", Log::DEBUG, "omx_vid_rend ChangeComponentState Execute");
1227 DeAllocateCodecsOMX();
1232 OMX_CONFIG_DISPLAYREGIONTYPE dispconf;
1233 memset(&dispconf,0,sizeof(dispconf));
1234 dispconf.nSize=sizeof(dispconf);
1235 dispconf.nVersion.nVersion=OMX_VERSION;
1237 dispconf.nPortIndex=omx_rend_input_port;
1239 dispconf.set=OMX_DISPLAY_SET_LAYER ;
1241 error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
1242 if (error!=OMX_ErrorNone){
1243 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
1244 DeAllocateCodecsOMX();
1248 /* dispconf.set=OMX_DISPLAY_SET_FULLSCREEN ;
1249 dispconf.fullscreen=OMX_FALSE;
1250 error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
1251 if (error!=OMX_ErrorNone){
1252 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
1253 DeAllocateCodecsOMX();
1257 dispconf.set=OMX_DISPLAY_SET_DEST_RECT;
1258 dispconf.dest_rect.x_offset=100;
1259 dispconf.dest_rect.y_offset=100;
1260 dispconf.dest_rect.width=640;
1261 dispconf.dest_rect.height=480;
1262 error=OMX_SetParameter(omx_vid_rend,OMX_IndexConfigDisplayRegion,&dispconf);
1263 if (error!=OMX_ErrorNone){
1264 Log::getInstance()->log("Video", Log::DEBUG, "Init OMX_IndexConfigDisplayRegion failed %x", error);
1265 DeAllocateCodecsOMX();
1272 if (!ChangeComponentState(omx_clock,OMX_StateExecuting)) {
1273 Log::getInstance()->log("Video", Log::DEBUG, "omx_clock ChangeComponentState Exccute");
1274 DeAllocateCodecsOMX();
1284 int VideoVPEOGL::ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type)
1286 OMX_ERRORTYPE error;
1287 error=OMX_SendCommand(handle,OMX_CommandStateSet,type,0);
1288 if (error!=OMX_ErrorNone){
1289 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to OMX State %x %x",handle,type, error);
1293 if (!CommandFinished(handle,OMX_CommandStateSet,type)) {
1301 int VideoVPEOGL::EnablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait)
1303 OMX_ERRORTYPE error;
1304 error=OMX_SendCommand(handle,OMX_CommandPortEnable,port,0);
1305 if (error!=OMX_ErrorNone){
1306 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to enable port %x %x",handle,port, error);
1310 if (!wait) return 1;
1311 if (!CommandFinished(handle,OMX_CommandPortEnable,port)) {
1319 int VideoVPEOGL::DisablePort(OMX_HANDLETYPE handle,OMX_U32 port,bool wait)
1321 OMX_ERRORTYPE error;
1322 error=OMX_SendCommand(handle,OMX_CommandPortDisable,port,0);
1323 if (error!=OMX_ErrorNone){
1324 Log::getInstance()->log("Video", Log::DEBUG, "handle %x Send Command to disable port %x %x",handle,port, error);
1328 if (!wait) return 1;
1329 if (!CommandFinished(handle,OMX_CommandPortDisable,port)) {
1340 int VideoVPEOGL::CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2)
1344 omx_event_mutex.Lock();
1345 list<VPE_OMX_EVENT>::iterator itty=omx_events.begin();
1346 while (itty!=omx_events.end()) {
1348 VPE_OMX_EVENT current=*itty;
1349 if (current.handle==handle) { //this is ours
1350 if (current.event_type==OMX_EventError) {
1351 omx_events.erase(itty);
1352 omx_event_mutex.Unlock();
1355 } else if (current.event_type==OMX_EventCmdComplete && current.data1==command && current.data2==data2) {
1356 omx_events.erase(itty);
1357 omx_event_mutex.Unlock();
1364 omx_event_mutex.Unlock();
1369 Log::getInstance()->log("Video", Log::DEBUG, "CommandFinished waited too long %x %x %x",handle,command, data2);
1378 int VideoVPEOGL::PrepareInputBufsOMX()
1380 OMX_ERRORTYPE error;
1381 OMX_PARAM_PORTDEFINITIONTYPE port_def_type;
1382 memset(&port_def_type,0,sizeof(port_def_type));
1383 port_def_type.nSize=sizeof(port_def_type);
1384 port_def_type.nVersion.nVersion=OMX_VERSION;
1385 port_def_type.nPortIndex=omx_codec_input_port;
1387 error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type);
1389 if (error!=OMX_ErrorNone){
1390 Log::getInstance()->log("Video", Log::DEBUG, "Get OMX OMX_IndexParamPortDefinition failed %x", error);
1392 /* Log::getInstance()->log("Video", Log::DEBUG, "Port para %d %d %d %d %d %d %d", port_def_type.nBufferCountActual,
1393 port_def_type.nBufferCountMin,port_def_type.nBufferSize,port_def_type.bEnabled,port_def_type.bPopulated,
1394 port_def_type.bBuffersContiguous,port_def_type.nBufferAlignment);*/
1396 port_def_type.nBufferCountActual=60;
1398 error=OMX_SetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_def_type);
1400 if (error!=OMX_ErrorNone){
1401 Log::getInstance()->log("Video", Log::DEBUG, "Set OMX OMX_IndexParamPortDefinition failed %x", error);
1405 error=OMX_SendCommand(omx_vid_dec,OMX_CommandPortEnable,omx_codec_input_port,0);
1406 if (error!=OMX_ErrorNone){
1407 Log::getInstance()->log("Video", Log::DEBUG, "Prepare Input bufs Send Command to enable port %x", error);
1411 input_bufs_omx_mutex.Lock();
1412 for (unsigned int i=0; i< port_def_type.nBufferCountActual;i++) {
1414 // unsigned char* new_buffer_data=(unsigned char*)malloc(port_def_type.nbufferSize);
1415 OMX_BUFFERHEADERTYPE *buf_head=NULL;
1416 /* error=OMX_Usebuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nbufferSize,new_buffer_data);
1417 if (error!=OMX_ErrorNone){
1418 Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_Usebuffer failed %x", error);
1419 input_bufs_omx_mutex.Unlock();
1422 error=OMX_AllocateBuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nBufferSize);
1423 if (error!=OMX_ErrorNone){
1424 Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_AllocateBuffer failed %x", error);
1425 input_bufs_omx_mutex.Unlock();
1428 input_bufs_omx_all.push_back(buf_head);
1429 input_bufs_omx_free.push_back(buf_head);
1431 omx_first_frame=true;
1434 cur_input_buf_omx=NULL;
1435 input_bufs_omx_mutex.Unlock();
1438 Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark3");
1439 if (!CommandFinished(omx_vid_dec,OMX_CommandPortEnable,omx_codec_input_port)) {
1442 Log::getInstance()->log("Video", Log::DEBUG, "PrepareInputBufsOMX mark4");
1447 int VideoVPEOGL::DestroyInputBufsOMX()
1449 OMX_ERRORTYPE error;
1451 cur_input_buf_omx=NULL;
1452 input_bufs_omx_mutex.Lock();
1453 for (int i=0; i< input_bufs_omx_all.size();i++) {
1454 // free(input_bufs_omx_all[i]->pBuffer);
1455 // input_bufs_omx_all[i]->pBuffer=NULL;
1456 error=OMX_FreeBuffer(omx_vid_dec,omx_codec_input_port,input_bufs_omx_all[i]);
1457 if (error!=OMX_ErrorNone){
1458 Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_FreeBuffer failed %x", error);
1459 input_bufs_omx_mutex.Unlock();
1463 input_bufs_omx_all.clear();
1464 input_bufs_omx_free.clear();
1465 input_bufs_omx_mutex.Unlock();
1472 int VideoVPEOGL::DeAllocateCodecsOMX()
1474 OMX_ERRORTYPE error;
1477 // first flush all buffers
1479 error=OMX_SendCommand(omx_vid_dec,OMX_CommandFlush, omx_codec_output_port, NULL);
1480 if (error!=OMX_ErrorNone){
1481 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush codec out failed %x", error);
1485 error=OMX_SendCommand(omx_vid_sched,OMX_CommandFlush, omx_shed_input_port, NULL);
1486 if (error!=OMX_ErrorNone){
1487 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush shed in failed %x", error);
1491 if (!CommandFinished(omx_vid_dec,OMX_CommandFlush,omx_codec_output_port) ||
1492 !CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_input_port)) {
1493 Log::getInstance()->log("Video", Log::DEBUG, "flush cmd codec shed failed");
1496 error=OMX_SendCommand(omx_clock,OMX_CommandFlush, omx_clock_output_port, NULL);
1497 if (error!=OMX_ErrorNone){
1498 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush clock out failed %x", error);
1502 error=OMX_SendCommand(omx_vid_sched,OMX_CommandFlush, omx_shed_clock_port, NULL);
1503 if (error!=OMX_ErrorNone){
1504 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush shed clock failed %x", error);
1508 if (!CommandFinished(omx_clock,OMX_CommandFlush,omx_clock_output_port) ||
1509 !CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_clock_port)) {
1510 Log::getInstance()->log("Video", Log::DEBUG, "flush cmd clock shed failed");
1513 error=OMX_SendCommand(omx_vid_sched,OMX_CommandFlush, omx_shed_output_port, NULL);
1514 if (error!=OMX_ErrorNone) {
1515 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush shed out failed %x", error);
1519 error=OMX_SendCommand(omx_vid_rend,OMX_CommandFlush, omx_rend_input_port, NULL);
1520 if (error!=OMX_ErrorNone) {
1521 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush rend in failed %x", error);
1525 if (!CommandFinished(omx_vid_sched,OMX_CommandFlush,omx_shed_output_port) ||
1526 !CommandFinished(omx_vid_rend,OMX_CommandFlush,omx_rend_input_port)) {
1527 Log::getInstance()->log("Video", Log::DEBUG, "flush cmd shed rend failed");
1533 error=OMX_SendCommand(omx_vid_dec,OMX_CommandFlush, omx_codec_input_port, NULL);
1534 if (error!=OMX_ErrorNone){
1535 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Flush codec out failed %x", error);
1540 if (!CommandFinished(omx_vid_dec,OMX_CommandFlush,omx_codec_input_port)) {
1541 Log::getInstance()->log("Video", Log::DEBUG, "flush cmd codec input failed");
1544 DestroyInputBufsOMX();
1547 if (!DisablePort(omx_vid_rend,omx_rend_input_port,true)) {
1548 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 1");
1550 if (!DisablePort(omx_vid_sched,omx_shed_output_port,true)) {
1551 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 2 ");
1554 error=OMX_SetupTunnel(omx_vid_rend,omx_rend_input_port,NULL,NULL);
1555 if (error!=OMX_ErrorNone){
1556 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1560 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_output_port,NULL,NULL);
1561 if (error!=OMX_ErrorNone){
1562 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1566 if (!DisablePort(omx_vid_sched,omx_shed_input_port,true)) {
1567 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 3");
1570 if (!DisablePort(omx_vid_sched,omx_shed_clock_port,true)) {
1571 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 4");
1574 if (!DisablePort(omx_clock,omx_clock_output_port,true)) {
1575 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 5");
1577 if (!DisablePort(omx_vid_dec,omx_codec_output_port,true)) {
1578 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 6");
1583 if (!DisablePort(omx_vid_dec,omx_codec_input_port,true)) {
1584 Log::getInstance()->log("Video", Log::DEBUG, "Disable Tunnel Port failed 7");
1588 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_input_port,NULL,NULL);
1589 if (error!=OMX_ErrorNone){
1590 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1593 error=OMX_SetupTunnel(omx_vid_sched,omx_shed_clock_port,NULL,NULL);
1594 if (error!=OMX_ErrorNone){
1595 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1599 error=OMX_SetupTunnel(omx_clock,omx_clock_output_port,NULL,NULL);
1600 if (error!=OMX_ErrorNone){
1601 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1605 error=OMX_SetupTunnel(omx_vid_dec,omx_codec_output_port,NULL,NULL);
1606 if (error!=OMX_ErrorNone){
1607 Log::getInstance()->log("Video", Log::DEBUG, "OMX_Setup tunnel teardown failed %x", error);
1615 error=OMX_FreeHandle(omx_vid_dec);
1616 error=OMX_FreeHandle(omx_vid_sched);
1617 error=OMX_FreeHandle(omx_vid_rend);
1618 error=OMX_FreeHandle(omx_clock);
1620 if (error!=OMX_ErrorNone) {
1621 Log::getInstance()->log("Video", Log::DEBUG, "FreeHandle failed %d", error);
1631 #ifdef VPE_LIBAV_SUPPORT
1633 enum PixelFormat VideoVPEOGL::get_format_libav(struct AVCodecContext *s, const enum PixelFormat *fmt)
1635 int dec_mode=((VideoVPEOGL*)getInstance())->getlibavDecodingMode();
1636 enum PixelFormat ret_pix=PIX_FMT_NONE;
1637 if (dec_mode==VPE_NO_XVMC) return PIX_FMT_NONE;
1638 while (*fmt!=PIX_FMT_NONE) {
1639 if (*fmt== PIX_FMT_XVMC_MPEG2_IDCT && dec_mode==VPE_XVMC_IDCT) {
1640 ret_pix=PIX_FMT_XVMC_MPEG2_IDCT;
1641 } else if (*fmt== PIX_FMT_XVMC_MPEG2_MC && dec_mode==VPE_XVMC_MOCOMP) {
1642 ret_pix=PIX_FMT_XVMC_MPEG2_MC;
1649 // we use this function to push the data to ogl out before hand, this is only useful for xvmc
1650 void VideoVPEOGL::draw_horiz_band_libav(struct AVCodecContext *s, const AVFrame *src, int offset[4], int y, int type, int height)
1652 if ((y+height)==src->height) {
1653 /* 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,
1654 ((xvmc_pix_fmt *)src->data[2])->picture_structure);*/
1655 if (((xvmc_pix_fmt *)src->data[2])->picture_structure!=3) {
1656 Log::getInstance()->log("Video", Log::ERR, "Non frame pict not supported! Yet! Please send sample to authors!"); exit(0);
1658 ((VideoVPEOGL*)Video::getInstance())->add_dec_frame_upload_only(s,src);
1663 int VideoVPEOGL::reget_buffer_libav(struct AVCodecContext *c, AVFrame *pic)
1665 Log::getInstance()->log("Video", Log::ERR, "Buffer reusing! Should not happen!Not Implemented!");
1669 int VideoVPEOGL::get_buffer_libav(struct AVCodecContext *c, AVFrame *pic)
1671 unsigned int want_sizes[4]={0,0,0,0};
1673 bool normal_pixs=false;
1675 int num_dct_blocks=0;
1678 //reget logic from mplayer
1679 if (pic->opaque && pic->data[0] && (!pic->buffer_hints ||pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE )){
1680 Log::getInstance()->log("Video", Log::ERR, "Buffer reusing! Should not happen!");
1685 if (c->pix_fmt!=PIX_FMT_XVMC_MPEG2_IDCT &&c->pix_fmt!=PIX_FMT_XVMC_MPEG2_MC) {
1687 // standard pixel format
1688 // this is written using much inspiration from libav util.c, so portions from there
1694 avcodec_align_dimensions2(c, &width, &height, s_a);
1695 if ((c->flags & CODEC_FLAG_EMU_EDGE)==0) {
1699 // Now we have to determine alignment size
1700 bool unaligned=true;
1702 av_image_fill_linesizes(pict.linesize, c->pix_fmt, width); //linesizes are derived
1703 width+=width & ~(width-1); //trick from libav, now determine, if the alignment is ok
1705 for (int i=0;i<4;i++) {
1706 if ((pict.linesize[i]%s_a[i])!=0) {
1712 int tot_size=av_image_fill_pointers(pict.data, c->pix_fmt, height, NULL, pict.linesize); //get sizes
1713 for (int i=0;i<4 ;i++) {
1714 if (i<3 && pict.data[i+1]) {
1715 want_sizes[i]=pict.data[i+1]-pict.data[i];
1718 want_sizes[i]=(tot_size-(pict.data[i]-pict.data[0]));
1725 //TODO set linesizes!
1727 num_blocks=((c->width+15)/16)*((c->height+15)/16);
1728 num_dct_blocks=num_blocks*6; //6 blocks per macroblock
1730 want_sizes[2]=sizeof(xvmc_pix_fmt);
1731 want_sizes[1]=sizeof(short)*num_dct_blocks*8*8;
1732 want_sizes[0]=sizeof(XvMCMacroBlock)*num_blocks;
1733 pict.linesize[0]=pict.linesize[1]=pict.linesize[2]=pict.linesize[3]=0;
1737 VPE_FrameBuf *frame_buf=((VideoVPEOGL*)Video::getInstance())->getFrameBuf(want_sizes);
1738 frame_buf->ogl_ref=NULL; //do not use old references, crash instead!
1739 frame_buf->ogl_uploaded=false; //not uploaded yet
1740 frame_buf->width=pic->width;
1741 frame_buf->height=pic->height;
1742 frame_buf->stride=pic->linesize[0];
1744 //Log::getInstance()->log("Video", Log::NOTICE, "get buffer %x",frame_buf);
1746 Log::getInstance()->log("Video", Log::ERR, "Getting buffer libav failed");
1752 pic->type=FF_BUFFER_TYPE_USER; // we are controlling the buffers
1753 int hchr_shift,vchr_shift;
1754 avcodec_get_chroma_sub_sample(c->pix_fmt,&hchr_shift,&vchr_shift);
1755 const int pixel_size = av_pix_fmt_descriptors[c->pix_fmt].comp[0].step_minus1+1;
1756 for (int i=0;i<4;i++) {
1757 pic->data[i]=(uint8_t*)frame_buf->data[i];
1758 pic->linesize[i]=pict.linesize[i];
1764 edge_width>>=hchr_shift;
1765 edge_height>>=vchr_shift;
1767 pic->data[i]+=FFALIGN((pic->linesize[i]*16) + (pixel_size*edge_width), s_a[i]);
1771 pic->base[0]=(uint8_t*)frame_buf; // our structure
1772 //pic->extended_data=pic->data;
1773 if(c->pkt) pic->pkt_pts=c->pkt->pts;
1774 else pic->pkt_pts=AV_NOPTS_VALUE;
1775 pic->width=c->width;
1776 pic->height=c->height;
1777 pic->format=c->pix_fmt;
1778 pic->sample_aspect_ratio=c->sample_aspect_ratio;
1779 pic->reordered_opaque= c->reordered_opaque;
1782 xvmc_pix_fmt *pix_xvmc=(xvmc_pix_fmt *)pic->data[2];
1783 pix_xvmc->xvmc_id=AV_XVMC_ID;
1784 pix_xvmc->data_blocks=(short*)pic->data[1];
1785 pix_xvmc->mv_blocks=(XvMCMacroBlock*)pic->data[0];
1786 pix_xvmc->allocated_mv_blocks=num_blocks;
1787 pix_xvmc->allocated_data_blocks=num_dct_blocks;
1788 if (c->pix_fmt==PIX_FMT_XVMC_MPEG2_IDCT) pix_xvmc->idct=1;
1789 else pix_xvmc->idct=0;
1790 pix_xvmc->unsigned_intra=1; // let see what happens
1791 pix_xvmc->p_surface=(XvMCSurface*)frame_buf->pict_num;
1792 pix_xvmc->start_mv_blocks_num=0;
1793 pix_xvmc->filled_mv_blocks_num=0;
1794 pix_xvmc->next_free_data_block_num=0;
1804 void VideoVPEOGL::release_buffer_libav(struct AVCodecContext *c, AVFrame *pic)
1806 // Log::getInstance()->log("Video", Log::NOTICE, "release buffer %x",pic->base[0]);
1807 ((VideoVPEOGL*)Video::getInstance())->releaseFrameBufLibav((VPE_FrameBuf*) pic->base[0]);
1809 pic->data[0]=pic->data[1]=pic->data[2]=pic->data[3]=NULL;
1814 int VideoVPEOGL::AllocateCodecsLibav()
1816 if (libav_running) DeAllocateCodecsLibav();
1817 libav_hastime=false;
1818 Log::getInstance()->log("Video", Log::NOTICE, "AllocateCodecslibav");
1819 mpeg2codec_context_libav=avcodec_alloc_context();
1820 if (mpeg2codec_context_libav==NULL) {
1821 Log::getInstance()->log("Video", Log::DEBUG, "Creating libav codec context failed");
1824 if (decoding_mode!=VPE_NO_XVMC) {
1825 mpeg2codec_context_libav->slice_flags=SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
1826 if (decoding_mode==VPE_XVMC_MOCOMP) mpeg2codec_context_libav->pix_fmt=PIX_FMT_XVMC_MPEG2_MC;
1827 else mpeg2codec_context_libav->pix_fmt=PIX_FMT_XVMC_MPEG2_IDCT;
1828 mpeg2codec_context_libav->get_format=get_format_libav;
1829 mpeg2codec_context_libav->draw_horiz_band=draw_horiz_band_libav;
1832 mpeg2codec_context_libav->get_buffer=get_buffer_libav;
1833 mpeg2codec_context_libav->reget_buffer=reget_buffer_libav;
1834 mpeg2codec_context_libav->release_buffer=release_buffer_libav;
1838 int avc_ret=avcodec_open(mpeg2codec_context_libav, mpeg2codec_libav);
1840 Log::getInstance()->log("Video", Log::DEBUG, "Opening libav codec failed ");
1843 memset(&incom_packet_libav,0,sizeof(incom_packet_libav));
1844 incom_packet_libav_size=200000;
1845 incom_packet_libav.data=(uint8_t*)av_malloc(incom_packet_libav_size+FF_INPUT_BUFFER_PADDING_SIZE);
1847 dec_frame_libav_mutex.Lock();
1848 for (int i=0;i<3;i++) {
1849 AVFrame *dec_frame_libav=avcodec_alloc_frame(); // may be we need multiple frames, if we want to use async texture upload
1850 if (!dec_frame_libav) {
1851 Log::getInstance()->log("Video", Log::DEBUG, "Allocating dec_frame failed");
1854 dec_frame_libav_all.push_back(dec_frame_libav);
1855 dec_frame_libav_free.push_back(dec_frame_libav);
1857 dec_frame_libav_decoding=NULL;
1858 dec_frame_libav_mutex.Unlock();
1860 ogl_frame_mutex.Lock();
1861 //Allocate texture structs, since we do not know the sizes, we do not allocate the textures yet
1862 for (int i=0;i<5;i++) {
1863 VPEOGLFrame *new_frame=(VPEOGLFrame *)malloc(sizeof(VPEOGLFrame));
1864 new_frame->type=1; //1 = YUV, 2 RGB
1865 new_frame->textures[0]=0;
1866 new_frame->textures[1]=0;
1867 new_frame->textures[2]=0;
1868 new_frame->width=new_frame->height=0;
1869 all_ogl_frames.push_back(new_frame);
1870 free_ogl_frames.push_back(new_frame);
1873 ogl_frame_outside=false;
1875 ogl_frame_mutex.Unlock();
1877 if (decoding_mode==VPE_XVMC_MOCOMP || decoding_mode==VPE_XVMC_IDCT) {
1878 OsdOpenGL* osd=(OsdOpenGL*)osd->getInstance();
1879 osd->BeginPainting(); // get OpenGl context
1880 moco_shader=new GLMocoShader();
1881 moco_shader->init();
1891 int VideoVPEOGL::DeAllocateCodecsLibav()
1893 libav_running=false;
1894 Log::getInstance()->log("Video", Log::NOTICE, "DeAllocateCodecslibav");
1895 dec_frame_libav_mutex.Lock();
1896 dec_frame_libav_upload_and_view_pending.clear();
1897 dec_frame_libav_upload_only_pending.clear();
1898 dec_frame_libav_free.clear();
1899 dec_frame_libav_mutex.Unlock();
1900 while (dec_frame_libav_uploading_framebuf) {
1901 Log::getInstance()->log("Video", Log::NOTICE, "Wait for uploading to finish");
1904 dec_frame_libav_mutex.Lock();
1905 for (int i=0; i< dec_frame_libav_all.size();i++) {
1906 av_free(dec_frame_libav_all[i]);
1909 dec_frame_libav_all.clear();
1911 av_free(incom_packet_libav.data);
1912 incom_packet_libav.data=NULL;
1913 incom_packet_libav_size=0;
1915 dec_frame_libav_mutex.Unlock();
1916 dec_frame_libav_decoding=NULL;
1917 while (ogl_frame_outside) {
1918 Log::getInstance()->log("Video", Log::NOTICE, "Wait for ogl frame from outside");
1922 ((OsdOpenGL*)Osd::getInstance())->BeginPainting(); // get osd's context
1923 ogl_frame_mutex.Lock();
1924 for (int i=0; i< dec_frame_libav_all.size();i++) {
1925 VPEOGLFrame * del_frame=all_ogl_frames[i];
1926 if (del_frame->textures[0]==0) {
1927 glDeleteTextures(1,&del_frame->textures[0]);
1928 del_frame->textures[0]=0;
1930 if (del_frame->textures[1]==0) {
1931 glDeleteTextures(1,&del_frame->textures[1]);
1932 del_frame->textures[1]=0;
1934 if (del_frame->textures[2]==0) {
1935 glDeleteTextures(1,&del_frame->textures[2]);
1936 del_frame->textures[2]=0;
1939 free(all_ogl_frames[i]);
1941 all_ogl_frames.clear();
1942 free_ogl_frames.clear();
1943 ready_ogl_frames.clear();
1944 recycle_ref_ogl_frames.clear();
1945 ogl_forward_ref_frame_num=0;
1946 ogl_backward_ref_frame_num=0;
1947 ogl_forward_ref_frame=NULL;
1948 ogl_backward_ref_frame=NULL;
1950 ogl_frame_mutex.Unlock();
1951 ((OsdOpenGL*)Osd::getInstance())->EndPainting();
1954 if (mpeg2codec_context_libav) {
1955 avcodec_close(mpeg2codec_context_libav);
1956 av_free(mpeg2codec_context_libav);
1957 mpeg2codec_context_libav=NULL;
1963 vpe_framebuf_mutex.Lock();
1965 for (int i=0;i<all_frame_bufs.size();i++) {
1966 VPE_FrameBuf* current=all_frame_bufs[i];
1967 for (int x=0;x<4;x++) {
1968 if (current->data[x]) {
1969 av_free(current->data[x]);
1974 all_frame_bufs.clear();
1975 free_frame_bufs.clear();
1976 locked_libav_frame_buf.clear();
1977 locked_uploading_frame_buf.clear();
1979 vpe_framebuf_mutex.Unlock();
1984 OsdOpenGL* osd=(OsdOpenGL*)osd->getInstance();
1985 osd->BeginPainting(); // get OpenGl context
1986 moco_shader->deinit();
2000 VPE_FrameBuf *VideoVPEOGL::getFrameBuf(unsigned int *size)
2002 VPE_FrameBuf* current=NULL;
2003 vpe_framebuf_mutex.Lock();
2004 if (free_frame_bufs.size()>0) {
2005 current=free_frame_bufs.front();
2006 free_frame_bufs.pop_front();
2007 } else if (all_frame_bufs.size()<6) {
2008 current=(VPE_FrameBuf*)malloc(sizeof(VPE_FrameBuf));
2009 memset(current,0,sizeof(VPE_FrameBuf));
2011 Log::getInstance()->log("Video", Log::NOTICE, "Framebuffer underrun!");
2012 vpe_framebuf_mutex.Unlock();
2013 return NULL; // We do not have a frame buffer
2015 locked_libav_frame_buf.push_back(current);
2016 vpe_framebuf_mutex.Unlock();
2017 //check if we need reallocation
2018 for (int x=0;x<4;x++) {
2019 if (current->size[x]!=size[x]) {
2020 current->data[x]=av_realloc(current->data[x],size[x]);
2021 current->size[x]=size[x];
2024 framebuf_framenum++;
2025 current->pict_num=framebuf_framenum; //This is used for tracking reference frames through the conversion pipeline
2030 void VideoVPEOGL::lockFrameBufUpload(VPE_FrameBuf* buf)
2032 // first find frame_buf memory
2034 //Log::getInstance()->log("Video", Log::NOTICE, "lock buffer upload %x",buf);
2035 VPE_FrameBuf* current=buf;
2036 vpe_framebuf_mutex.Lock();
2037 if (current) locked_uploading_frame_buf.push_back(current); //locked
2038 vpe_framebuf_mutex.Unlock();
2043 void VideoVPEOGL::releaseFrameBufLibav(VPE_FrameBuf* buf)
2045 // first find frame_buf memory
2046 //Log::getInstance()->log("Video", Log::NOTICE, "release buffer libav %x",buf);
2047 VPE_FrameBuf* current=buf;
2048 vpe_framebuf_mutex.Lock();
2050 locked_libav_frame_buf.remove(current); //unlocked
2051 list<VPE_FrameBuf*>::iterator itty=locked_uploading_frame_buf.begin();
2053 while (itty!=locked_uploading_frame_buf.end()) {
2054 if (*itty==current) {
2061 free_frame_bufs.push_back(current);
2064 vpe_framebuf_mutex.Unlock();
2067 void VideoVPEOGL::releaseFrameBufUpload(VPE_FrameBuf* buf)
2069 // first find frame_buf memory
2070 VPE_FrameBuf* current=buf;
2071 //Log::getInstance()->log("Video", Log::NOTICE, "release buffer upload %x",buf);
2072 vpe_framebuf_mutex.Lock();
2074 locked_uploading_frame_buf.remove(current); //unlocked
2075 list<VPE_FrameBuf*>::iterator itty=locked_libav_frame_buf.begin();
2077 while (itty!=locked_libav_frame_buf.end()) {
2078 if (*itty==current) {
2085 free_frame_bufs.push_back(current);
2088 vpe_framebuf_mutex.Unlock();
2091 void VideoVPEOGL::add_dec_frame_upload_only(struct AVCodecContext *s,const AVFrame* data)
2093 dec_frame_libav_mutex.Lock();
2094 libavwidth=s->width;
2095 libavheight=s->height;
2096 libavpixfmt=s->pix_fmt;
2097 //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]);
2099 dec_frame_libav_upload_only_pending.push_back((VPE_FrameBuf*)data->base[0]); // we are only uploading
2100 dec_frame_libav_mutex.Unlock();
2110 int VideoVPEOGL::stop()
2112 if (!initted) return 0;
2114 #ifdef VPE_OMX_SUPPORT
2115 //Check if libav mode
2116 if (decoding_backend==VPE_DECODER_OMX) DeAllocateCodecsOMX();
2123 // if (ioctl(fdVideo, AV_SET_VID_STOP, 0) != 0) return 0;
2127 int VideoVPEOGL::reset()
2129 if (!initted) return 0;
2131 // if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0;
2135 int VideoVPEOGL::pause()
2137 if (!initted) return 0;
2139 // if (ioctl(fdVideo, AV_SET_VID_PAUSE, 0) != 0) return 0;
2143 int VideoVPEOGL::unPause() // FIXME get rid - same as play!!
2145 if (!initted) return 0;
2146 // if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
2150 int VideoVPEOGL::fastForward()
2152 if (!initted) return 0;
2154 // if (ioctl(fdVideo, AV_SET_VID_libavWD, 1) != 0) return 0;
2158 int VideoVPEOGL::unFastForward()
2160 if (!initted) return 0;
2162 // if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; // don't need this.
2164 //// if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
2168 int VideoVPEOGL::attachFrameBuffer()
2170 if (!initted) return 0;
2172 // if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
2176 int VideoVPEOGL::blank(void)
2178 // if (ioctl(fdVideo, AV_SET_VID_FB, 1) != 0) return 0;
2179 // if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
2183 ULLONG VideoVPEOGL::getCurrentTimestamp()
2185 /* sync_data_t timestamps;
2186 if (ioctl(fdVideo, AV_GET_VID_TIMESTAMPS, ×tamps) == 0)
2188 // FIXME are these the right way around?
2190 timestamps.stc = (timestamps.stc >> 31 ) | (timestamps.stc & 1);
2191 timestamps.pts = (timestamps.pts >> 31 ) | (timestamps.pts & 1);
2193 return timestamps.stc;
2202 ULONG VideoVPEOGL::timecodeToFrameNumber(ULLONG timecode)
2204 if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
2205 else return (ULONG)(((double)timecode / (double)90000) * (double)30);
2209 int VideoVPEOGL::test()
2214 // return ioctl(fdVideo, AV_SET_VID_STC, &stc);
2221 int VideoVPEOGL::test2()
2227 void VideoVPEOGL::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
2229 mediapacket = mplist.front();
2232 UINT VideoVPEOGL::DeliverMediaSample(UCHAR* buffer, UINT *samplepos)
2234 DeliverMediaPacket(mediapacket, buffer, samplepos);
2235 if (*samplepos == mediapacket.length) {
2242 UINT VideoVPEOGL::DeliverMediaPacket(MediaPacket packet,
2243 const UCHAR* buffer,
2246 if (packet.type == MPTYPE_VIDEO_H264)
2254 switch (decoding_backend) {
2255 default: case 0: return 0; // no backend runnigng
2256 #ifdef VPE_OMX_SUPPORT
2257 case VPE_DECODER_OMX: return DeliverMediaPacketOMX(packet,buffer,samplepos);
2259 #ifdef VPE_LIBAV_SUPPORT
2260 case VPE_DECODER_libav: return DeliverMediaPacketlibav(packet,buffer,samplepos);
2265 #ifdef VPE_OMX_SUPPORT
2266 UINT VideoVPEOGL::DeliverMediaPacketOMX(MediaPacket packet,
2267 const UCHAR* buffer,
2272 //Later add fail back code for libav
2274 *samplepos+=packet.length;
2275 return packet.length;
2279 if (!omx_running) return 0; // if we are not runnig do not do this
2282 OMX_ERRORTYPE error;
2284 /* OMX_PARAM_PORTDEFINITIONTYPE port_image;
2285 memset(&port_image,0,sizeof(port_image));
2286 port_image.nSize=sizeof(port_image);
2287 port_image.nVersion.nVersion=OMX_VERSION;
2288 port_image.nPortIndex =omx_codec_output_port;
2289 error=OMX_GetParameter(omx_vid_dec,OMX_IndexParamPortDefinition, &port_image);
2290 if (error!= OMX_ErrorNone){
2291 Log::getInstance()->log("Video", Log::DEBUG, "OMX_GetParameter failed %x", error);
2293 Log::getInstance()->log("Video", Log::DEBUG, "Image port %d %d", port_image.format.video.nFrameWidth , port_image.format.video.nFrameHeight);*/
2295 /*First Check, if we have an audio sample*/
2299 return 0; //Not in iframe mode!
2303 if (packet.disconti) {
2305 if (cur_input_buf_omx) {
2306 OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx);
2307 if (error!=OMX_ErrorNone){
2308 Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error);
2310 cur_input_buf_omx=NULL;
2314 /*Inspect PES-Header */
2316 // OMX_STATETYPE temp_state;
2317 // OMX_GetState(omx_vid_dec,&temp_state);
2319 if (*samplepos==0) {//stripheader
2320 headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
2321 *samplepos+=headerstrip;
2322 if ( packet.synched ) {
2324 if (cur_input_buf_omx) {
2325 OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx);
2326 if (error!=OMX_ErrorNone){
2327 Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error);
2330 cur_input_buf_omx=NULL;//write out old data
2332 // reftime1=packet.presentation_time;
2333 // reftime2=reftime1+1;
2336 if (!firstsynched) {//
2337 *samplepos=packet.length;//if we have not processed at least one
2338 return packet.length;//synched packet ignore it!
2343 if (!cur_input_buf_omx) {
2344 input_bufs_omx_mutex.Lock();
2345 if (input_bufs_omx_free.size()==0) {
2346 input_bufs_omx_mutex.Unlock();
2347 Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket no free sample");
2348 return 0; // we do not have a free media sample
2351 cur_input_buf_omx=input_bufs_omx_free.front();
2352 cur_input_buf_omx->nFilledLen=0;
2353 cur_input_buf_omx->nOffset=0;
2354 cur_input_buf_omx->nTimeStamp=0;
2355 input_bufs_omx_free.pop_front();
2356 input_bufs_omx_mutex.Unlock();
2362 if (cur_input_buf_omx->nFilledLen==0) {//will only be changed on first packet
2363 /*if (packet.disconti) {
2364 ms->SetDiscontinuity(TRUE);
2366 ms->SetDiscontinuity(FALSE);
2368 //if (packet.synched) {
2370 //lastreftimePTS=packet.pts;
2371 if (omx_first_frame) { // TODO time
2372 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_STARTTIME;
2373 omx_first_frame=false;
2379 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
2382 // ms->SetSyncPoint(TRUE);
2386 unsigned int haveToCopy=packet.length-*samplepos;
2388 while (haveToCopy> (cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen)) {
2389 unsigned int cancopy=cur_input_buf_omx->nAllocLen-cur_input_buf_omx->nFilledLen;
2390 memcpy(cur_input_buf_omx->pBuffer+cur_input_buf_omx->nFilledLen,buffer+packet.pos_buffer+*samplepos,cancopy);
2391 haveToCopy-=cancopy;
2392 cur_input_buf_omx->nFilledLen+=cancopy;
2393 *samplepos+=cancopy;
2394 // push old buffer out
2396 OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx);
2397 if (error!=OMX_ErrorNone){
2398 Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error);
2401 input_bufs_omx_mutex.Lock();
2402 if (input_bufs_omx_free.size()==0) {
2403 input_bufs_omx_mutex.Unlock();
2404 //Log::getInstance()->log("Video", Log::DEBUG, "Deliver MediaPacket no free sample");
2405 return *samplepos; // we do not have a free media sample
2407 cur_input_buf_omx=input_bufs_omx_free.front();
2408 cur_input_buf_omx->nFilledLen=0;
2409 cur_input_buf_omx->nOffset=0;
2410 cur_input_buf_omx->nTimeStamp=0;
2411 input_bufs_omx_free.pop_front();
2412 input_bufs_omx_mutex.Unlock();
2414 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
2417 memcpy(cur_input_buf_omx->pBuffer+cur_input_buf_omx->nFilledLen,
2418 buffer+packet.pos_buffer+*samplepos,haveToCopy);
2419 cur_input_buf_omx->nFilledLen+=haveToCopy;
2423 *samplepos+=haveToCopy;
2432 #ifdef VPE_LIBAV_SUPPORT
2433 int VideoVPEOGL::DecodePacketlibav()
2435 unsigned int haveToCopy=incom_packet_libav.size;
2436 if (incom_packet_libav.size==0) return 1; // we are already empty
2437 while (haveToCopy>0) {
2441 // Log::getInstance()->log("Video", Log::DEBUG, "Push data to decoder");
2443 #ifdef BENCHMARK_FPS
2444 int cur_time=getTimeMS();
2446 dec_bytes=avcodec_decode_video2(mpeg2codec_context_libav, dec_frame_libav_decoding,
2447 &frame_ready, &incom_packet_libav);
2448 #ifdef BENCHMARK_FPS
2449 time_in_decoder+=getTimeMS()-cur_time;
2450 if (frame_ready) num_frames++;
2451 if ((num_frames%100)==0) {
2452 float fps=1000./(float)(time_in_decoder);
2453 fps*=((float)num_frames);
2454 Log::getInstance()->log("Video", Log::NOTICE, "Current Pure Decoding FPS %g", fps);
2458 Log::getInstance()->log("Video", Log::DEBUG, "Decoding frame failed %x", dec_bytes);
2461 haveToCopy-=dec_bytes;
2463 // Log::getInstance()->log("Video", Log::DEBUG, "We have a frame push it to osd");
2465 lockFrameBufUpload((VPE_FrameBuf*)dec_frame_libav_decoding->base[0]); //lock for upload, so that ffmpeg does not reuse
2466 dec_frame_libav_mutex.Lock();
2467 libavwidth=mpeg2codec_context_libav->width;
2468 libavheight=mpeg2codec_context_libav->height;
2469 libavpixfmt=mpeg2codec_context_libav->pix_fmt;
2470 // Log::getInstance()->log("Video", Log::DEBUG, "Frame info %d %d %d",libavwidth,libavheight,libavpixfmt);
2471 // Log::getInstance()->log("Video", Log::DEBUG, "Frame info %d %d %d %d %x",libavwidth,libavheight,libavpixfmt,
2472 // ((VPE_FrameBuf*)dec_frame_libav_decoding->base[0])->pict_num,dec_frame_libav_decoding->base[0]);
2475 dec_frame_libav_upload_and_view_pending.push_back(dec_frame_libav_decoding);
2476 dec_frame_libav_decoding=NULL;
2477 if (dec_frame_libav_free.size()>0) {
2478 dec_frame_libav_decoding=dec_frame_libav_free.front();
2479 dec_frame_libav_free.pop_front();
2480 dec_frame_libav_mutex.Unlock();
2482 libav_hastime=false;
2484 libav_hastime=false;
2485 dec_frame_libav_mutex.Unlock();
2486 Log::getInstance()->log("Video", Log::DEBUG, "We have no free buffers 2 FPS");
2496 incom_packet_libav.size=0;
2502 UINT VideoVPEOGL::DeliverMediaPacketlibav(MediaPacket packet,
2503 const UCHAR* buffer,
2506 //Later add fail back code for libav
2508 *samplepos+=packet.length;
2509 return packet.length;
2512 if (!libav_running) return 0; // if we are not runnig do not do this
2518 return 0; //Not in iframe mode!
2522 if (packet.disconti) {
2524 if (!DecodePacketlibav()) return 0;
2527 /*Inspect PES-Header */
2528 if (!dec_frame_libav_decoding) {
2529 dec_frame_libav_mutex.Lock();
2530 if (dec_frame_libav_free.size()>0) {
2531 dec_frame_libav_decoding=dec_frame_libav_free.front();
2532 dec_frame_libav_free.pop_front();
2533 dec_frame_libav_mutex.Unlock();
2535 Log::getInstance()->log("Video", Log::DEBUG, "We have no free buffers FPS");
2536 dec_frame_libav_mutex.Unlock();
2544 if (*samplepos==0) {//stripheader
2545 headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
2546 *samplepos+=headerstrip;
2547 if ( packet.synched ) {
2549 if (!DecodePacketlibav()) return 0; // WriteOut old Data
2551 libav_time=packet.presentation_time;
2553 // reftime1=packet.presentation_time;
2554 // reftime2=reftime1+1;
2557 if (!firstsynched) {//
2558 *samplepos=packet.length;//if we have not processed at least one
2559 return packet.length;//synched packet ignore it!
2569 /*if (cur_input_buf_omx->nFilledLen==0) {//will only be changed on first packet
2570 /*if (packet.disconti) {
2571 ms->SetDiscontinuity(TRUE);
2573 ms->SetDiscontinuity(FALSE);
2575 //if (packet.synched) {
2577 //lastreftimePTS=packet.pts;
2578 if (omx_first_frame) { // TODO time
2579 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_STARTTIME;
2580 omx_first_frame=false;
2586 cur_input_buf_omx->nFlags=OMX_BUFFERFLAG_TIME_UNKNOWN;
2589 // ms->SetSyncPoint(TRUE);
2593 unsigned int haveToCopy=packet.length-*samplepos;
2595 if ((incom_packet_libav_size-incom_packet_libav.size)< haveToCopy) {
2596 // if the buffer is to small reallocate
2597 incom_packet_libav_size+=haveToCopy;
2598 incom_packet_libav.data=(uint8_t*)av_realloc(incom_packet_libav.data,incom_packet_libav_size+FF_INPUT_BUFFER_PADDING_SIZE);
2599 Log::getInstance()->log("Video", Log::DEBUG, "Reallocate avpacket buffer to %d", incom_packet_libav_size);
2601 memcpy(incom_packet_libav.data+incom_packet_libav.size,buffer+packet.pos_buffer+*samplepos,haveToCopy);
2602 incom_packet_libav.size+=haveToCopy;
2604 *samplepos+=haveToCopy;
2619 void VideoVPEOGL::ResetTimeOffsets()
2623 bool VideoVPEOGL::displayIFrame(const UCHAR* buffer, UINT length)
2625 //write(fdVideo, buffer, length);
2626 if (!iframemode) EnterIframePlayback();
2627 // WriteOutTS(buffer,length, h264?MPTYPE_VIDEO_H264 :MPTYPE_VIDEO_MPEG2 );
2633 int VideoVPEOGL::EnterIframePlayback()