From 08d170b644b16246fbde43ca2d0ca8e75b85940b Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sat, 9 Jun 2012 14:24:25 +0200 Subject: [PATCH] Add input buffer for ffmpeg, fix broken decoding --- GNUmakefile | 5 +- videovpeogl.cc | 164 +++++++++++++++++++++++++++---------------------- videovpeogl.h | 7 +++ 3 files changed, 101 insertions(+), 75 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 680bc08..3508184 100755 --- a/GNUmakefile +++ b/GNUmakefile @@ -48,7 +48,8 @@ LIBS = -lpthread -lrt OBJECTS += main.o threadp.o remotemvp.o ledmvp.o mtdmvp.o videomvp.o audiomvp.o osdmvp.o surfacemvp.o vmedialist.o vcolourtuner.o vmediaview.o vvideomedia.o TIOBJECT = ticonfig.o CROSSLIBS = ../jpeg/jpeg-6b/libjpeg.a -INCLUDES = -I../jpeg/jpeg-6b -DVOMP_PLATTFORM_MVP +INCLUDES = -I../jpeg/jpeg-6b -DVOMP_PLATTFORM_MVP + endif @@ -61,6 +62,8 @@ OBJECTS += main.o threadp.o osdopengl.o surfaceopengl.o ledraspberry.o mtdraspbe LIBS+= -ljpeg CROSSLIBS = INCLUDES = -DVOMP_PLATTFORM_RASPBERRY -I/opt/vc/include +CXXFLAGS_DEV += -D__STDC_CONSTANT_MACROS +CXXFLAGS_REL += -D__STDC_CONSTANT_MACROS endif diff --git a/videovpeogl.cc b/videovpeogl.cc index c4ec0c5..d5bc781 100755 --- a/videovpeogl.cc +++ b/videovpeogl.cc @@ -48,7 +48,7 @@ VideoVPEOGL::VideoVPEOGL() dec_frame_ff_decoding=NULL; ogl_frame_outside=false; #endif - + #ifdef BENCHMARK_FPS time_in_decoder=0; num_frames=0; @@ -1345,9 +1345,11 @@ int VideoVPEOGL::AllocateCodecsFFMPEG() Log::getInstance()->log("Video", Log::DEBUG, "Opening ffmpeg codec failed"); return 0; } - Log::getInstance()->log("Video", Log::NOTICE, "AllocateCodecsFFmpeg mark1"); + memset(&incom_packet_ff,0,sizeof(incom_packet_ff)); + incom_packet_ff_size=200000; + incom_packet_ff.data=(uint8_t*)av_malloc(incom_packet_ff_size+FF_INPUT_BUFFER_PADDING_SIZE); + dec_frame_ff_mutex.Lock(); - Log::getInstance()->log("Video", Log::NOTICE, "AllocateCodecsFFmpeg mark2"); for (int i=0;i<3;i++) { AVFrame *dec_frame_ff=avcodec_alloc_frame(); // may be we need multiple frames, if we want to use async texture upload if (!dec_frame_ff) { @@ -1358,7 +1360,6 @@ int VideoVPEOGL::AllocateCodecsFFMPEG() dec_frame_ff_free.push_back(dec_frame_ff); } dec_frame_ff_decoding=NULL; - Log::getInstance()->log("Video", Log::NOTICE, "AllocateCodecsFFmpeg mark 3"); dec_frame_ff_mutex.Unlock(); ogl_frame_mutex.Lock(); @@ -1402,6 +1403,11 @@ int VideoVPEOGL::DeAllocateCodecsFFMPEG() } dec_frame_ff_all.clear(); + + av_free(incom_packet_ff.data); + incom_packet_ff.data=NULL; + incom_packet_ff_size=0; + dec_frame_ff_mutex.Unlock(); dec_frame_ff_decoding=NULL; while (ogl_frame_outside) { @@ -1463,7 +1469,7 @@ int VideoVPEOGL::stop() #endif - + // if (ioctl(fdVideo, AV_SET_VID_STOP, 0) != 0) return 0; return 1; @@ -1472,7 +1478,7 @@ int VideoVPEOGL::stop() int VideoVPEOGL::reset() { if (!initted) return 0; - + // if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; return 1; } @@ -1775,6 +1781,70 @@ UINT VideoVPEOGL::DeliverMediaPacketOMX(MediaPacket packet, #ifdef VPE_FFMPEG_SUPPORT +int VideoVPEOGL::DecodePacketFFMPEG() +{ + unsigned int haveToCopy=incom_packet_ff.size; + if (incom_packet_ff.size==0) return 1; // we are already empty + while (haveToCopy>0) { + int dec_bytes=0; + int frame_ready=0; + + // Log::getInstance()->log("Video", Log::DEBUG, "Push data to decoder"); + +#ifdef BENCHMARK_FPS + int cur_time=getTimeMS(); +#endif + + dec_bytes=avcodec_decode_video2(mpeg2codec_context_ff, dec_frame_ff_decoding, + &frame_ready, &incom_packet_ff); +#ifdef BENCHMARK_FPS + time_in_decoder+=getTimeMS()-cur_time; + if (frame_ready) num_frames++; + if ((num_frames%100)==0) { + float fps=1000./(float)(time_in_decoder); + fps*=((float)num_frames); + Log::getInstance()->log("Video", Log::NOTICE, "Current Pure Decoding FPS %g", fps); + } +#endif + if (dec_bytes<0) { + Log::getInstance()->log("Video", Log::DEBUG, "Decoding frame failed %x", dec_bytes); + return 0; + } + haveToCopy-=dec_bytes; + if (frame_ready) { + // Log::getInstance()->log("Video", Log::DEBUG, "We have a frame push it to osd"); + + dec_frame_ff_mutex.Lock(); + ffwidth=mpeg2codec_context_ff->width; + ffheight=mpeg2codec_context_ff->height; + ffpixfmt=mpeg2codec_context_ff->pix_fmt; + // Log::getInstance()->log("Video", Log::DEBUG, "Frame info %d %d %d",ffwidth,ffheight,ffpixfmt); + + dec_frame_ff_upload_pending.push_back(dec_frame_ff_decoding); + dec_frame_ff_decoding=NULL; + if (dec_frame_ff_free.size()>0) { + dec_frame_ff_decoding=dec_frame_ff_free.front(); + dec_frame_ff_free.pop_front(); + dec_frame_ff_mutex.Unlock(); + threadSignal(); + ffmpeg_hastime=false; + } else { + ffmpeg_hastime=false; + dec_frame_ff_mutex.Unlock(); + // No free Buffers + return 0; + } + + + } + + } + incom_packet_ff.size=0; + return 1; + +} + + UINT VideoVPEOGL::DeliverMediaPacketFFMPEG(MediaPacket packet, const UCHAR* buffer, UINT *samplepos) @@ -1795,16 +1865,10 @@ UINT VideoVPEOGL::DeliverMediaPacketFFMPEG(MediaPacket packet, } UINT headerstrip=0; -/* if (packet.disconti) { + if (packet.disconti) { firstsynched=false; - if (cur_input_buf_omx) { - OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error); - } - cur_input_buf_omx=NULL; - } - }*/ + if (!DecodePacketFFMPEG()) return 0; + } /*Inspect PES-Header */ if (!dec_frame_ff_decoding) { @@ -1828,14 +1892,8 @@ UINT VideoVPEOGL::DeliverMediaPacketFFMPEG(MediaPacket packet, *samplepos+=headerstrip; if ( packet.synched ) { - /*if (cur_input_buf_omx) { - OMX_ERRORTYPE error=OMX_EmptyThisBuffer(omx_vid_dec,cur_input_buf_omx); - if (error!=OMX_ErrorNone){ - Log::getInstance()->log("Video", Log::DEBUG, "OMX_EmptyThisBuffer failed %x", error); - } + if (!DecodePacketFFMPEG()) return 0; // WriteOut old Data - cur_input_buf_omx=NULL;//write out old data - }*/ ffmpeg_time=packet.presentation_time; ffmpeg_hastime=true; // reftime1=packet.presentation_time; @@ -1879,61 +1937,19 @@ UINT VideoVPEOGL::DeliverMediaPacketFFMPEG(MediaPacket packet, }*/ unsigned int haveToCopy=packet.length-*samplepos; - while (haveToCopy>0) { - int dec_bytes=0; - int frame_ready=0; - - // Log::getInstance()->log("Video", Log::DEBUG, "Push data to decoder"); - -#ifdef BENCHMARK_FPS - int cur_time=getTimeMS(); -#endif - - dec_bytes=avcodec_decode_video(mpeg2codec_context_ff, dec_frame_ff_decoding, - &frame_ready, buffer+packet.pos_buffer+*samplepos, haveToCopy); -#ifdef BENCHMARK_FPS - time_in_decoder+=getTimeMS()-cur_time; - if (frame_ready) num_frames++; - if ((num_frames%100)==0) { - float fps=1000./(float)(time_in_decoder); - fps*=((float)num_frames); - Log::getInstance()->log("Video", Log::NOTICE, "Current Pure Decoding FPS %g", fps); - } -#endif - if (dec_bytes<0) { - Log::getInstance()->log("Video", Log::DEBUG, "Decoding frame failed %x", dec_bytes); - return *samplepos; - } - *samplepos+=dec_bytes; - haveToCopy-=dec_bytes; - if (frame_ready) { - // Log::getInstance()->log("Video", Log::DEBUG, "We have a frame push it to osd"); - dec_frame_ff_mutex.Lock(); - ffwidth=mpeg2codec_context_ff->width; - ffheight=mpeg2codec_context_ff->height; - ffpixfmt=mpeg2codec_context_ff->pix_fmt; - // Log::getInstance()->log("Video", Log::DEBUG, "Frame info %d %d %d",ffwidth,ffheight,ffpixfmt); - - dec_frame_ff_upload_pending.push_back(dec_frame_ff_decoding); - dec_frame_ff_decoding=NULL; - if (dec_frame_ff_free.size()>0) { - dec_frame_ff_decoding=dec_frame_ff_free.front(); - dec_frame_ff_free.pop_front(); - dec_frame_ff_mutex.Unlock(); - threadSignal(); - ffmpeg_hastime=false; - } else { - ffmpeg_hastime=false; - dec_frame_ff_mutex.Unlock(); - // No free Buffers - return *samplepos; - } + if ((incom_packet_ff_size-incom_packet_ff.size)< haveToCopy) { + // if the buffer is to small reallocate + incom_packet_ff_size+=haveToCopy; + incom_packet_ff.data=(uint8_t*)av_realloc(incom_packet_ff.data,incom_packet_ff_size+FF_INPUT_BUFFER_PADDING_SIZE); + Log::getInstance()->log("Video", Log::DEBUG, "Reallocate avpacket buffer to %d", incom_packet_ff_size); + } + memcpy(incom_packet_ff.data,buffer+packet.pos_buffer+*samplepos,haveToCopy); + incom_packet_ff.size+=haveToCopy; + *samplepos+=haveToCopy; - } - } return *samplepos; @@ -1955,7 +1971,7 @@ bool VideoVPEOGL::displayIFrame(const UCHAR* buffer, UINT length) //write(fdVideo, buffer, length); if (!iframemode) EnterIframePlayback(); // WriteOutTS(buffer,length, h264?MPTYPE_VIDEO_H264 :MPTYPE_VIDEO_MPEG2 ); - + lastpacketnum=-1; return true; } diff --git a/videovpeogl.h b/videovpeogl.h index 3c722e6..c127a33 100755 --- a/videovpeogl.h +++ b/videovpeogl.h @@ -66,7 +66,10 @@ struct VPE_OMX_EVENT { #endif #ifdef VPE_FFMPEG_SUPPORT + +#include extern "C" { + #include #include } @@ -236,6 +239,9 @@ class VideoVPEOGL : public Video, public Thread_TYPE list dec_frame_ff_upload_pending; AVFrame* dec_frame_ff_uploading; AVFrame* dec_frame_ff_decoding; + + AVPacket incom_packet_ff; + int incom_packet_ff_size; Mutex dec_frame_ff_mutex; @@ -243,6 +249,7 @@ class VideoVPEOGL : public Video, public Thread_TYPE UINT DeliverMediaPacketFFMPEG(MediaPacket packet,const UCHAR* buffer,UINT *samplepos); int AllocateCodecsFFMPEG(); int DeAllocateCodecsFFMPEG(); + int DecodePacketFFMPEG(); bool ffmpeg_running; bool ffmpeg_hastime; // signals if a pts is now long long ffmpeg_time; -- 2.39.2