omx_h264=omx_mpeg2=true;
#endif
-#ifdef VPE_FFMPEG_SUPPORT
- mpeg2codec_context_ff=NULL;
- ffmpeg_running=false;
- dec_frame_ff_uploading=NULL;
- dec_frame_ff_decoding=NULL;
+#ifdef VPE_LIBAV_SUPPORT
+ mpeg2codec_context_libav=NULL;
+ libav_running=false;
+ dec_frame_libav_uploading=NULL;
+ dec_frame_libav_decoding=NULL;
ogl_frame_outside=false;
+ decoding_mode=VPE_NO_XVMC;
+ //decoding_mode=VPE_XVMC_MOCOMP;
#endif
#ifdef BENCHMARK_FPS
/* if (format == PAL) setLetterboxBorder("38");
else setLetterboxBorder("31");*/
- /* new stuff */
+ /* new stulibav */
#endif
-#ifdef VPE_FFMPEG_SUPPORT
+#ifdef VPE_LIBAV_SUPPORT
av_register_all();
- mpeg2codec_ff=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO);
- //mpeg2codec_ff=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO_XVMC);
- if (mpeg2codec_ff==NULL) {
- Log::getInstance()->log("Video", Log::DEBUG, "Find ffmpeg mpeg2 codec failed");
+ if (decoding_mode==VPE_NO_XVMC) {
+ mpeg2codec_libav=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO);
+ } else {
+ mpeg2codec_libav=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO_XVMC);
+ }
+ if (mpeg2codec_libav==NULL) {
+ Log::getInstance()->log("Video", Log::DEBUG, "Find libav mpeg2 codec failed");
return 0;
}
DeAllocateCodecsOMX();
OMX_Deinit();
#endif
-#ifdef VPE_FFMPEG_SUPPORT
- DeAllocateCodecsFFMPEG();
+#ifdef VPE_LIBAV_SUPPORT
+ DeAllocateCodecsLibav();
#endif
eglDestroyContext(egl_display,egl_context);
// close(fdVideo);
}
while (1) {
bool sleep=true;
-#ifdef VPE_FFMPEG_SUPPORT
- dec_frame_ff_mutex.Lock();
- if (dec_frame_ff_upload_pending.size()>0) {
- dec_frame_ff_uploading=dec_frame_ff_upload_pending.front();
- dec_frame_ff_upload_pending.pop_front();
- if (dec_frame_ff_upload_pending.size()>0) sleep=false;
+#ifdef VPE_LIBAV_SUPPORT
+ dec_frame_libav_mutex.Lock();
+ if (dec_frame_libav_upload_pending.size()>0) {
+ dec_frame_libav_uploading=dec_frame_libav_upload_pending.front();
+ dec_frame_libav_upload_pending.pop_front();
+ if (dec_frame_libav_upload_pending.size()>0) sleep=false;
}
- dec_frame_ff_mutex.Unlock();
- if (dec_frame_ff_uploading) {
+ dec_frame_libav_mutex.Unlock();
+ if (dec_frame_libav_uploading) {
int width,height,pixfmt;
//First get a free ogl image
VPEOGLFrame* out_frame=NULL;
}
if (free_ogl_frames.size()>0) {
- width=ffwidth;
- height=ffheight;
- pixfmt=ffpixfmt;
+ width=libavwidth;
+ height=libavheight;
+ pixfmt=libavpixfmt;
out_frame=free_ogl_frames.front();
free_ogl_frames.pop_front();
} else MILLISLEEP(2);
bool failed=false;
if (out_frame) {
if (out_frame->textures[0]==0 || out_frame->width!=width ||
- out_frame->height!=height || out_frame->stride!=dec_frame_ff_uploading->linesize[0]) {
- if (out_frame->textures[0]==0) {
+ out_frame->height!=height || out_frame->stride!=dec_frame_libav_uploading->linesize[0]) {
+ if (out_frame->textures[0]!=0) {
glDeleteTextures(1,&out_frame->textures[0]);
out_frame->textures[0]=0;
}
- if (out_frame->textures[1]==0) {
+ if (out_frame->textures[1]!=0) {
glDeleteTextures(1,&out_frame->textures[1]);
out_frame->textures[1]=0;
}
- if (out_frame->textures[2]==0) {
+ if (out_frame->textures[2]!=0) {
glDeleteTextures(1,&out_frame->textures[2]);
out_frame->textures[2]=0;
}
- if (!AllocateYUVOglTexture(out_frame,width,height,dec_frame_ff_uploading->linesize[0])) failed=true;
+ if (!AllocateYUVOglTexture(out_frame,width,height,dec_frame_libav_uploading->linesize[0])) failed=true;
}
if (!failed) {
//up to now only YUV data, this is for reference only, since the pi is too slow.
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
out_frame->stride,out_frame->height,
GL_LUMINANCE,GL_UNSIGNED_BYTE,
- dec_frame_ff_uploading->data[0]);
+ dec_frame_libav_uploading->data[0]);
glBindTexture(GL_TEXTURE_2D, out_frame->textures[1]);
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
out_frame->stride>>1,out_frame->height>>1,
GL_LUMINANCE,GL_UNSIGNED_BYTE,
- dec_frame_ff_uploading->data[1]);
+ dec_frame_libav_uploading->data[1]);
glBindTexture(GL_TEXTURE_2D, out_frame->textures[2]);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
out_frame->stride>>1,out_frame->height>>1,
GL_LUMINANCE,GL_UNSIGNED_BYTE,
- dec_frame_ff_uploading->data[2]);
+ dec_frame_libav_uploading->data[2]);
+
+
+ releaseFrameBufUpload((VPE_FrameBuf*)dec_frame_libav_uploading->base[0]);
+
+
ogl_frame_mutex.Lock();
ready_ogl_frames.push_back(out_frame);
ogl_frame_mutex.Unlock();
}
- dec_frame_ff_mutex.Lock();
- dec_frame_ff_free.push_back(dec_frame_ff_uploading);
- dec_frame_ff_uploading=NULL;
- dec_frame_ff_mutex.Unlock();
+ dec_frame_libav_mutex.Lock();
+ dec_frame_libav_free.push_back(dec_frame_libav_uploading);
+ dec_frame_libav_uploading=NULL;
+ dec_frame_libav_mutex.Unlock();
void VideoVPEOGL::threadPostStopCleanup()
{
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
-#ifdef VPE_FFMPEG_SUPPORT
- dec_frame_ff_uploading=NULL;
+#ifdef VPE_LIBAV_SUPPORT
+ dec_frame_libav_uploading=NULL;
#endif
}
close(fdVideo);
if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
if (!setSource()) { shutdown(); return 0; }
- if (!attachFrameBuffer()) { shutdown(); return 0; }
+ if (!attachFramebuffer()) { shutdown(); return 0; }
// Reopening the fd causes the scart aspect line to go back to 4:3
// Set this again to the same as the tv screen size
if (AllocateCodecsOMX()) {
decoding_backend=VPE_DECODER_OMX;
return 1;
- // Otherwise fall back to ffmpeg
+ // Otherwise fall back to libav
} else {
if (h264) {
omx_h264=false;
}
}
#endif
-#ifdef VPE_FFMPEG_SUPPORT
- if (AllocateCodecsFFMPEG()) {
- decoding_backend=VPE_DECODER_FFMPEG;
+#ifdef VPE_LIBAV_SUPPORT
+ if (AllocateCodecsLibav()) {
+ decoding_backend=VPE_DECODER_libav;
return 1;
- // Otherwise fall back to ffmpeg
+ // Otherwise fall back to libav
}
#endif
return 0;
input_bufs_omx_mutex.Lock();
for (unsigned int i=0; i< port_def_type.nBufferCountActual;i++) {
- // unsigned char* new_buffer_data=(unsigned char*)malloc(port_def_type.nBufferSize);
+ // unsigned char* new_buffer_data=(unsigned char*)malloc(port_def_type.nbufferSize);
OMX_BUFFERHEADERTYPE *buf_head=NULL;
- /* error=OMX_UseBuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nBufferSize,new_buffer_data);
+ /* error=OMX_Usebuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nbufferSize,new_buffer_data);
if (error!=OMX_ErrorNone){
- Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_UseBuffer failed %x", error);
+ Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_Usebuffer failed %x", error);
input_bufs_omx_mutex.Unlock();
return 0;
}*/
#endif
-#ifdef VPE_FFMPEG_SUPPORT
+#ifdef VPE_LIBAV_SUPPORT
+
+enum PixelFormat VideoVPEOGL::get_format_libav(struct AVCodecContext *s, const enum PixelFormat *fmt)
+{
+ int dec_mode=((VideoVPEOGL*)getInstance())->getlibavDecodingMode();
+ enum PixelFormat ret_pix=PIX_FMT_NONE;
+ if (dec_mode==VPE_NO_XVMC) return PIX_FMT_NONE;
+ while (*fmt!=PIX_FMT_NONE) {
+ if (*fmt== PIX_FMT_XVMC_MPEG2_IDCT && dec_mode==VPE_XVMC_IDCT) {
+ ret_pix=PIX_FMT_XVMC_MPEG2_IDCT;
+ } else if (*fmt== PIX_FMT_XVMC_MPEG2_MC && dec_mode==VPE_XVMC_MOCOMP) {
+ ret_pix=PIX_FMT_XVMC_MPEG2_MC;
+ }
+ fmt++;
+ }
+ return ret_pix;
+}
-int VideoVPEOGL::AllocateCodecsFFMPEG()
+int VideoVPEOGL::reget_buffer_libav(struct AVCodecContext *c, AVFrame *pic)
{
- ffmpeg_hastime=false;
- Log::getInstance()->log("Video", Log::NOTICE, "AllocateCodecsFFmpeg");
- mpeg2codec_context_ff=avcodec_alloc_context();
- if (mpeg2codec_context_ff==NULL) {
- Log::getInstance()->log("Video", Log::DEBUG, "Creating ffmpeg codec context failed");
+ Log::getInstance()->log("Video", Log::ERR, "Buffer reusing! Should not happen!Not Implemented!");
+ return -1;
+}
+
+int VideoVPEOGL::get_buffer_libav(struct AVCodecContext *c, AVFrame *pic)
+{
+ unsigned int want_sizes[4]={0,0,0,0};
+ AVPicture pict;
+ bool normal_pixs=false;
+ int s_a[4];
+ //reget logic from mplayer
+ if (pic->opaque && pic->data[0] && (!pic->buffer_hints ||pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE )){
+ Log::getInstance()->log("Video", Log::ERR, "Buffer reusing! Should not happen!");
return 0;
}
- if(avcodec_open(mpeg2codec_context_ff, mpeg2codec_ff)<0) {
- Log::getInstance()->log("Video", Log::DEBUG, "Opening ffmpeg codec failed");
+
+
+ if (c->pix_fmt!=PIX_FMT_XVMC_MPEG2_IDCT &&c->pix_fmt!=PIX_FMT_XVMC_MPEG2_MC) {
+ normal_pixs=true;
+ // standard pixel format
+ // this is written using much inspiration from libav util.c, so portions from there
+ int width,height;
+
+ width=c->width;
+ height=c->height;
+
+ avcodec_align_dimensions2(c, &width, &height, s_a);
+ if ((c->flags & CODEC_FLAG_EMU_EDGE)==0) {
+ width+=2*16;
+ height+=2*16;
+ }
+ // Now we have to determine alignment size
+ bool unaligned=true;
+ while (unaligned) {
+ av_image_fill_linesizes(pict.linesize, c->pix_fmt, width); //linesizes are derived
+ width+=width & ~(width-1); //trick from libav, now determine, if the alignment is ok
+ unaligned=false;
+ for (int i=0;i<4;i++) {
+ if ((pict.linesize[i]%s_a[i])!=0) {
+ unaligned=true;
+ break;
+ }
+ }
+ }
+ int tot_size=av_image_fill_pointers(pict.data, c->pix_fmt, height, NULL, pict.linesize); //get sizes
+ for (int i=0;i<4 ;i++) {
+ if (i<3 && pict.data[i+1]) {
+ want_sizes[i]=pict.data[i+1]-pict.data[i];
+ want_sizes[i]+=16;
+ } else {
+ want_sizes[i]=(tot_size-(pict.data[i]-pict.data[0]));
+ want_sizes[i]+=16;
+ break;
+ }
+ }
+
+ } else {
+ //TODE set linesizes!
+ Log::getInstance()->log("Video", Log::ERR, "Not implemented");
+ return -1;
+
+ }
+
+ VPE_FrameBuf *frame_buf=((VideoVPEOGL*)Video::getInstance())->getFrameBuf(want_sizes);
+ //Log::getInstance()->log("Video", Log::NOTICE, "get buffer %x",frame_buf);
+ if (!frame_buf) {
+ Log::getInstance()->log("Video", Log::ERR, "Getting buffer libav failed");
+ return -1;
+ }
+ //populate pict
+ pic->type=FF_BUFFER_TYPE_USER; // we are controlling the buffers
+ int hchr_shift,vchr_shift;
+ avcodec_get_chroma_sub_sample(c->pix_fmt,&hchr_shift,&vchr_shift);
+ const int pixel_size = av_pix_fmt_descriptors[c->pix_fmt].comp[0].step_minus1+1;
+ for (int i=0;i<4;i++) {
+ pic->data[i]=(uint8_t*)frame_buf->data[i];
+ pic->linesize[i]=pict.linesize[i];
+ if (normal_pixs) {
+
+ int edge_width=16;
+ int edge_height=16;
+ if (i!=0) {
+ edge_width>>=hchr_shift;
+ edge_height>>=vchr_shift;
+ }
+ pic->data[i]+=FFALIGN((pic->linesize[i]*16) + (pixel_size*edge_width), s_a[i]);
+ }
+ }
+
+ pic->base[0]=(uint8_t*)frame_buf; // our structure
+ //pic->extended_data=pic->data;
+ if(c->pkt) pic->pkt_pts=c->pkt->pts;
+ else pic->pkt_pts=AV_NOPTS_VALUE;
+ pic->width=c->width;
+ pic->height=c->height;
+ pic->format=c->pix_fmt;
+ pic->sample_aspect_ratio=c->sample_aspect_ratio;
+ pic->reordered_opaque= c->reordered_opaque;
+ pic->age=INT_MAX;
+
+ return 0;
+
+}
+
+void VideoVPEOGL::release_buffer_libav(struct AVCodecContext *c, AVFrame *pic)
+{
+// Log::getInstance()->log("Video", Log::NOTICE, "release buffer %x",pic->base[0]);
+ ((VideoVPEOGL*)Video::getInstance())->releaseFrameBufLibav((VPE_FrameBuf*) pic->base[0]);
+ pic->base[0]=NULL;
+ pic->data[0]=pic->data[1]=pic->data[2]=pic->data[3]=NULL;
+
+
+}
+
+int VideoVPEOGL::AllocateCodecsLibav()
+{
+ libav_hastime=false;
+ Log::getInstance()->log("Video", Log::NOTICE, "AllocateCodecslibav");
+ mpeg2codec_context_libav=avcodec_alloc_context();
+ if (mpeg2codec_context_libav==NULL) {
+ Log::getInstance()->log("Video", Log::DEBUG, "Creating libav codec context failed");
return 0;
}
- 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);
+ if (decoding_mode!=VPE_NO_XVMC) {
+ mpeg2codec_context_libav->slice_flags=SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
+ if (decoding_mode==VPE_XVMC_MOCOMP) mpeg2codec_context_libav->pix_fmt=PIX_FMT_XVMC_MPEG2_MC;
+ else mpeg2codec_context_libav->pix_fmt=PIX_FMT_XVMC_MPEG2_IDCT;
+ mpeg2codec_context_libav->get_format=get_format_libav;
+
+ }
+ mpeg2codec_context_libav->get_buffer=get_buffer_libav;
+ mpeg2codec_context_libav->reget_buffer=reget_buffer_libav;
+ mpeg2codec_context_libav->release_buffer=release_buffer_libav;
- dec_frame_ff_mutex.Lock();
+
+ int avc_ret=avcodec_open(mpeg2codec_context_libav, mpeg2codec_libav);
+ if (avc_ret<0) {
+ Log::getInstance()->log("Video", Log::DEBUG, "Opening libav codec failed ");
+ return 0;
+ }
+ memset(&incom_packet_libav,0,sizeof(incom_packet_libav));
+ incom_packet_libav_size=200000;
+ incom_packet_libav.data=(uint8_t*)av_malloc(incom_packet_libav_size+FF_INPUT_BUFFER_PADDING_SIZE);
+
+ dec_frame_libav_mutex.Lock();
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) {
+ AVFrame *dec_frame_libav=avcodec_alloc_frame(); // may be we need multiple frames, if we want to use async texture upload
+ if (!dec_frame_libav) {
Log::getInstance()->log("Video", Log::DEBUG, "Allocating dec_frame failed");
return 0;
}
- dec_frame_ff_all.push_back(dec_frame_ff);
- dec_frame_ff_free.push_back(dec_frame_ff);
+ dec_frame_libav_all.push_back(dec_frame_libav);
+ dec_frame_libav_free.push_back(dec_frame_libav);
}
- dec_frame_ff_decoding=NULL;
- dec_frame_ff_mutex.Unlock();
+ dec_frame_libav_decoding=NULL;
+ dec_frame_libav_mutex.Unlock();
ogl_frame_mutex.Lock();
//Allocate texture structs, since we do not know the sizes, we do not allocate the textures yet
ogl_frame_mutex.Unlock();
- ffmpeg_running=true;
+ libav_running=true;
return 1;
}
-int VideoVPEOGL::DeAllocateCodecsFFMPEG()
+int VideoVPEOGL::DeAllocateCodecsLibav()
{
- ffmpeg_running=false;
- Log::getInstance()->log("Video", Log::NOTICE, "DeAllocateCodecsFFmpeg");
- dec_frame_ff_mutex.Lock();
- dec_frame_ff_upload_pending.clear();
- dec_frame_ff_free.clear();
- dec_frame_ff_mutex.Unlock();
- while (dec_frame_ff_uploading) {
+ libav_running=false;
+ Log::getInstance()->log("Video", Log::NOTICE, "DeAllocateCodecslibav");
+ dec_frame_libav_mutex.Lock();
+ dec_frame_libav_upload_pending.clear();
+ dec_frame_libav_free.clear();
+ dec_frame_libav_mutex.Unlock();
+ while (dec_frame_libav_uploading) {
Log::getInstance()->log("Video", Log::NOTICE, "Wait for uploading to finish");
MILLISLEEP(20);
}
- dec_frame_ff_mutex.Lock();
- for (int i=0; i< dec_frame_ff_all.size();i++) {
- av_free(dec_frame_ff_all[i]);
+ dec_frame_libav_mutex.Lock();
+ for (int i=0; i< dec_frame_libav_all.size();i++) {
+ av_free(dec_frame_libav_all[i]);
}
- dec_frame_ff_all.clear();
+ dec_frame_libav_all.clear();
- av_free(incom_packet_ff.data);
- incom_packet_ff.data=NULL;
- incom_packet_ff_size=0;
+ av_free(incom_packet_libav.data);
+ incom_packet_libav.data=NULL;
+ incom_packet_libav_size=0;
- dec_frame_ff_mutex.Unlock();
- dec_frame_ff_decoding=NULL;
+ dec_frame_libav_mutex.Unlock();
+ dec_frame_libav_decoding=NULL;
while (ogl_frame_outside) {
Log::getInstance()->log("Video", Log::NOTICE, "Wait for ogl frame from outside");
MILLISLEEP(20);
((OsdOpenGL*)Osd::getInstance())->BeginPainting(); // get osd's context
ogl_frame_mutex.Lock();
- for (int i=0; i< dec_frame_ff_all.size();i++) {
+ for (int i=0; i< dec_frame_libav_all.size();i++) {
VPEOGLFrame * del_frame=all_ogl_frames[i];
if (del_frame->textures[0]==0) {
glDeleteTextures(1,&del_frame->textures[0]);
((OsdOpenGL*)Osd::getInstance())->EndPainting();
- if (mpeg2codec_context_ff) {
- avcodec_close(mpeg2codec_context_ff);
- av_free(mpeg2codec_context_ff);
- mpeg2codec_context_ff=NULL;
+ if (mpeg2codec_context_libav) {
+ avcodec_close(mpeg2codec_context_libav);
+ av_free(mpeg2codec_context_libav);
+ mpeg2codec_context_libav=NULL;
+
+ }
+
+
+ vpe_framebuf_mutex.Lock();
+
+ for (int i=0;i<all_frame_bufs.size();i++) {
+ VPE_FrameBuf* current=all_frame_bufs[i];
+ for (int x=0;x<4;x++) {
+ if (current->data[x]) {
+ av_free(current->data[x]);
+ }
+ }
+ free(current);
}
+ all_frame_bufs.clear();
+ free_frame_bufs.clear();
+ locked_libav_frame_buf.clear();
+ locked_uploading_frame_buf.clear();
+ vpe_framebuf_mutex.Unlock();
return 1;
}
+VPE_FrameBuf *VideoVPEOGL::getFrameBuf(unsigned int *size)
+{ //for libav
+ VPE_FrameBuf* current=NULL;
+ vpe_framebuf_mutex.Lock();
+ if (free_frame_bufs.size()>0) {
+ current=free_frame_bufs.front();
+ free_frame_bufs.pop_front();
+ } else if (all_frame_bufs.size()<6) {
+ current=(VPE_FrameBuf*)malloc(sizeof(VPE_FrameBuf));
+ memset(current,0,sizeof(VPE_FrameBuf));
+ } else {
+ Log::getInstance()->log("Video", Log::NOTICE, "Framebuffer underrun!");
+ vpe_framebuf_mutex.Unlock();
+ return NULL; // We do not have a frame buffer
+ }
+ locked_libav_frame_buf.push_back(current);
+ vpe_framebuf_mutex.Unlock();
+ //check if we need reallocation
+ for (int x=0;x<4;x++) {
+ if (current->size[x]!=size[x]) {
+ current->data[x]=av_realloc(current->data[x],size[x]);
+ current->size[x]=size[x];
+ }
+ }
+ return current;
+
+}
+
+void VideoVPEOGL::lockFrameBufUpload(VPE_FrameBuf* buf)
+{
+ // first find frame_buf memory
+
+ //Log::getInstance()->log("Video", Log::NOTICE, "lock buffer upload %x",buf);
+ VPE_FrameBuf* current=buf;
+ vpe_framebuf_mutex.Lock();
+ if (current) locked_uploading_frame_buf.push_back(current); //locked
+ vpe_framebuf_mutex.Unlock();
+
+}
+
+
+void VideoVPEOGL::releaseFrameBufLibav(VPE_FrameBuf* buf)
+{
+ // first find frame_buf memory
+ //Log::getInstance()->log("Video", Log::NOTICE, "release buffer libav %x",buf);
+ VPE_FrameBuf* current=buf;
+ vpe_framebuf_mutex.Lock();
+ if (current) {
+ locked_libav_frame_buf.remove(current); //unlocked
+ list<VPE_FrameBuf*>::iterator itty=locked_uploading_frame_buf.begin();
+ bool inlist=false;
+ while (itty!=locked_uploading_frame_buf.end()) {
+ if (*itty==current) {
+ inlist=true;
+ break;
+ }
+ itty++;
+ }
+ if (!inlist) {
+ free_frame_bufs.push_back(current);
+ }
+ }
+ vpe_framebuf_mutex.Unlock();
+}
+
+void VideoVPEOGL::releaseFrameBufUpload(VPE_FrameBuf* buf)
+{
+ // first find frame_buf memory
+ VPE_FrameBuf* current=buf;
+ //Log::getInstance()->log("Video", Log::NOTICE, "release buffer upload %x",buf);
+ vpe_framebuf_mutex.Lock();
+ if (current) {
+ locked_uploading_frame_buf.remove(current); //unlocked
+ list<VPE_FrameBuf*>::iterator itty=locked_libav_frame_buf.begin();
+ bool inlist=false;
+ while (itty!=locked_libav_frame_buf.end()) {
+ if (*itty==current) {
+ inlist=true;
+ break;
+ }
+ itty++;
+ }
+ if (!inlist) {
+ free_frame_bufs.push_back(current);
+ }
+ }
+ vpe_framebuf_mutex.Unlock();
+}
+
+
+
if (!initted) return 0;
#ifdef VPE_OMX_SUPPORT
- //Check if ffmpeg mode
+ //Check if libav mode
if (decoding_backend==VPE_DECODER_OMX) DeAllocateCodecsOMX();
decoding_backend=0;
{
if (!initted) return 0;
-// if (ioctl(fdVideo, AV_SET_VID_FFWD, 1) != 0) return 0;
+// if (ioctl(fdVideo, AV_SET_VID_libavWD, 1) != 0) return 0;
return 1;
}
#ifdef VPE_OMX_SUPPORT
case VPE_DECODER_OMX: return DeliverMediaPacketOMX(packet,buffer,samplepos);
#endif
-#ifdef VPE_FFMPEG_SUPPORT
- case VPE_DECODER_FFMPEG: return DeliverMediaPacketFFMPEG(packet,buffer,samplepos);
+#ifdef VPE_LIBAV_SUPPORT
+ case VPE_DECODER_libav: return DeliverMediaPacketlibav(packet,buffer,samplepos);
#endif
}
}
{
- //Later add fail back code for ffmpeg
+ //Later add fail back code for libav
/*if (!videoon) {
*samplepos+=packet.length;
return packet.length;
#endif
-#ifdef VPE_FFMPEG_SUPPORT
-int VideoVPEOGL::DecodePacketFFMPEG()
+#ifdef VPE_LIBAV_SUPPORT
+int VideoVPEOGL::DecodePacketlibav()
{
- unsigned int haveToCopy=incom_packet_ff.size;
- if (incom_packet_ff.size==0) return 1; // we are already empty
+ unsigned int haveToCopy=incom_packet_libav.size;
+ if (incom_packet_libav.size==0) return 1; // we are already empty
while (haveToCopy>0) {
int dec_bytes=0;
int frame_ready=0;
#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);
+ dec_bytes=avcodec_decode_video2(mpeg2codec_context_libav, dec_frame_libav_decoding,
+ &frame_ready, &incom_packet_libav);
#ifdef BENCHMARK_FPS
time_in_decoder+=getTimeMS()-cur_time;
if (frame_ready) num_frames++;
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();
+ lockFrameBufUpload((VPE_FrameBuf*)dec_frame_libav_decoding->base[0]); //lock for upload, so that ffmpeg does not reuse
+ dec_frame_libav_mutex.Lock();
+ libavwidth=mpeg2codec_context_libav->width;
+ libavheight=mpeg2codec_context_libav->height;
+ libavpixfmt=mpeg2codec_context_libav->pix_fmt;
+ // Log::getInstance()->log("Video", Log::DEBUG, "Frame info %d %d %d",libavwidth,libavheight,libavpixfmt);
+
+
+ dec_frame_libav_upload_pending.push_back(dec_frame_libav_decoding);
+ dec_frame_libav_decoding=NULL;
+ if (dec_frame_libav_free.size()>0) {
+ dec_frame_libav_decoding=dec_frame_libav_free.front();
+ dec_frame_libav_free.pop_front();
+ dec_frame_libav_mutex.Unlock();
threadSignal();
- ffmpeg_hastime=false;
+ libav_hastime=false;
} else {
- ffmpeg_hastime=false;
- dec_frame_ff_mutex.Unlock();
- // No free Buffers
+ libav_hastime=false;
+ dec_frame_libav_mutex.Unlock();
+ // No free buffers
return 0;
}
}
}
- incom_packet_ff.size=0;
+ incom_packet_libav.size=0;
return 1;
}
-UINT VideoVPEOGL::DeliverMediaPacketFFMPEG(MediaPacket packet,
+UINT VideoVPEOGL::DeliverMediaPacketlibav(MediaPacket packet,
const UCHAR* buffer,
UINT *samplepos)
{
- //Later add fail back code for ffmpeg
+ //Later add fail back code for libav
/*if (!videoon) {
*samplepos+=packet.length;
return packet.length;
}*/
- if (!ffmpeg_running) return 0; // if we are not runnig do not do this
+ if (!libav_running) return 0; // if we are not runnig do not do this
if (iframemode) {
UINT headerstrip=0;
if (packet.disconti) {
firstsynched=false;
- if (!DecodePacketFFMPEG()) return 0;
+ if (!DecodePacketlibav()) return 0;
}
/*Inspect PES-Header */
- if (!dec_frame_ff_decoding) {
- dec_frame_ff_mutex.Lock();
- 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();
+ if (!dec_frame_libav_decoding) {
+ dec_frame_libav_mutex.Lock();
+ if (dec_frame_libav_free.size()>0) {
+ dec_frame_libav_decoding=dec_frame_libav_free.front();
+ dec_frame_libav_free.pop_front();
+ dec_frame_libav_mutex.Unlock();
} else {
Log::getInstance()->log("Video", Log::DEBUG, "We have no free buffers");
- dec_frame_ff_mutex.Unlock();
- // No free Buffers
+ dec_frame_libav_mutex.Unlock();
+ // No free buffers
return 0;
}
}
*samplepos+=headerstrip;
if ( packet.synched ) {
- if (!DecodePacketFFMPEG()) return 0; // WriteOut old Data
+ if (!DecodePacketlibav()) return 0; // WriteOut old Data
- ffmpeg_time=packet.presentation_time;
- ffmpeg_hastime=true;
+ libav_time=packet.presentation_time;
+ libav_hastime=true;
// reftime1=packet.presentation_time;
// reftime2=reftime1+1;
firstsynched=true;
}*/
unsigned int haveToCopy=packet.length-*samplepos;
- if ((incom_packet_ff_size-incom_packet_ff.size)< haveToCopy) {
+ if ((incom_packet_libav_size-incom_packet_libav.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);
+ incom_packet_libav_size+=haveToCopy;
+ incom_packet_libav.data=(uint8_t*)av_realloc(incom_packet_libav.data,incom_packet_libav_size+FF_INPUT_BUFFER_PADDING_SIZE);
+ Log::getInstance()->log("Video", Log::DEBUG, "Reallocate avpacket buffer to %d", incom_packet_libav_size);
}
- memcpy(incom_packet_ff.data,buffer+packet.pos_buffer+*samplepos,haveToCopy);
- incom_packet_ff.size+=haveToCopy;
+ memcpy(incom_packet_libav.data+incom_packet_libav.size,buffer+packet.pos_buffer+*samplepos,haveToCopy);
+ incom_packet_libav.size+=haveToCopy;
*samplepos+=haveToCopy;
\r
#endif\r
\r
-#ifdef VPE_FFMPEG_SUPPORT\r
+#ifdef VPE_LIBAV_SUPPORT\r
\r
#include <stdint.h>\r
extern "C" {\r
\r
#include <libavcodec/avcodec.h>\r
#include <libavformat/avformat.h>\r
+#include <libavutil/imgutils.h>\r
}\r
+\r
+struct VPE_FrameBuf\r
+{ //This is a frame bulibaver, nothing fancy just plain memory\r
+ void *data[4];\r
+ unsigned int size[4];\r
+};\r
+\r
#endif\r
\r
\r
int attachFrameBuffer(); // What does this do?\r
ULONG timecodeToFrameNumber(ULLONG timecode);\r
ULLONG getCurrentTimestamp();\r
- bool displayIFrame(const UCHAR* buffer, UINT length);\r
+ bool displayIFrame(const UCHAR* bulibaver, UINT length);\r
\r
// Writing Data to Videodevice\r
virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);\r
- virtual UINT DeliverMediaSample(UCHAR* buffer, UINT* samplepos);\r
+ virtual UINT DeliverMediaSample(UCHAR* bulibaver, UINT* samplepos);\r
virtual long long SetStartOffset(long long curreftime, bool *rsync)\r
{ *rsync=false; return 0; };\r
virtual void ResetTimeOffsets();\r
\r
virtual bool supportsh264(){return true;};\r
\r
- int WriteOutTS(const unsigned char *buffer,int length, int type);\r
+ int WriteOutTS(const unsigned char *bulibaver,int length, int type);\r
void WriteOutPATPMT();\r
\r
\r
int initUsingOSDObjects();\r
int shutdownUsingOSDObjects() {return shutdown();};\r
\r
+#ifdef VPE_LIBAV_SUPPORT\r
+ int getlibavDecodingMode() {return decoding_mode;};\r
+\r
+\r
+#endif\r
+\r
private:\r
int EnterIframePlayback();\r
bool iframemode;\r
\r
UINT DeliverMediaPacket(MediaPacket packet,\r
- const UCHAR* buffer,\r
+ const UCHAR* bulibaver,\r
UINT *samplepos);\r
- int decoding_backend; //1 omx, 2 ffmpeg\r
+ int decoding_backend; //1 omx, 2 libav\r
#define VPE_DECODER_OMX 1\r
-#define VPE_DECODER_FFMPEG 2\r
+#define VPE_DECODER_libav 2\r
\r
#ifdef VPE_OMX_SUPPORT\r
static OMX_ERRORTYPE EventHandler_OMX(OMX_IN OMX_HANDLETYPE handle,OMX_IN OMX_PTR appdata,\r
OMX_IN OMX_EVENTTYPE event_type,OMX_IN OMX_U32 data1,\r
OMX_IN OMX_U32 data2,OMX_IN OMX_PTR event_data);\r
- static OMX_ERRORTYPE EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer);\r
- static OMX_ERRORTYPE FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer);\r
+ static OMX_ERRORTYPE EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver);\r
+ static OMX_ERRORTYPE FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver);\r
\r
UINT DeliverMediaPacketOMX(MediaPacket packet,\r
- const UCHAR* buffer,\r
+ const UCHAR* bulibaver,\r
UINT *samplepos);\r
\r
int PrepareInputBufsOMX();\r
int DestroyInputBufsOMX();\r
\r
void AddOmxEvent(VPE_OMX_EVENT new_event);\r
- void ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer);\r
+ void ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* bulibaver);\r
\r
int ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type);\r
int CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2);\r
\r
#endif\r
\r
-#ifdef VPE_FFMPEG_SUPPORT\r
- AVCodec *mpeg2codec_ff;\r
- AVCodecContext *mpeg2codec_context_ff;\r
- vector<AVFrame*> dec_frame_ff_all;\r
- list<AVFrame*> dec_frame_ff_free;\r
- list<AVFrame*> dec_frame_ff_upload_pending;\r
- AVFrame* dec_frame_ff_uploading;\r
- AVFrame* dec_frame_ff_decoding;\r
+#ifdef VPE_LIBAV_SUPPORT\r
+\r
+ const static int VPE_NO_XVMC=0;\r
+ const static int VPE_XVMC_MOCOMP=1;\r
+ const static int VPE_XVMC_IDCT=2;\r
+\r
+ int decoding_mode;\r
+\r
+ AVCodec *mpeg2codec_libav;\r
+ AVCodecContext *mpeg2codec_context_libav;\r
+ vector<AVFrame*> dec_frame_libav_all;\r
+ list<AVFrame*> dec_frame_libav_free;\r
+ list<AVFrame*> dec_frame_libav_upload_pending;\r
+ AVFrame* dec_frame_libav_uploading;\r
+ AVFrame* dec_frame_libav_decoding;\r
+\r
+ vector<VPE_FrameBuf*> all_frame_bufs;\r
+ list<VPE_FrameBuf*> free_frame_bufs;\r
+ list<VPE_FrameBuf*> locked_libav_frame_buf;\r
+ list<VPE_FrameBuf*> locked_uploading_frame_buf;\r
+\r
+ VPE_FrameBuf *getFrameBuf(unsigned int *size); //for libav\r
+ void releaseFrameBufLibav(VPE_FrameBuf*data);\r
+ void lockFrameBufUpload(VPE_FrameBuf* data);\r
+ void releaseFrameBufUpload(VPE_FrameBuf* data);\r
+\r
+ Mutex vpe_framebuf_mutex;\r
+\r
+\r
+\r
+ AVPacket incom_packet_libav;\r
+ int incom_packet_libav_size;\r
+ Mutex dec_frame_libav_mutex;\r
+\r
\r
- AVPacket incom_packet_ff;\r
- int incom_packet_ff_size;\r
- Mutex dec_frame_ff_mutex;\r
\r
+ UINT DeliverMediaPacketlibav(MediaPacket packet,const UCHAR* bulibaver,UINT *samplepos);\r
+ int AllocateCodecsLibav();\r
+ int DeAllocateCodecsLibav();\r
+ int DecodePacketlibav();\r
\r
+ static enum PixelFormat get_format_libav(struct AVCodecContext *s, const enum PixelFormat *fmt);\r
+ static int get_buffer_libav(struct AVCodecContext *c, AVFrame *pic);\r
+ static int reget_buffer_libav(struct AVCodecContext *c, AVFrame *pic);\r
+ static void release_buffer_libav(struct AVCodecContext *c, AVFrame *pic);\r
\r
- UINT DeliverMediaPacketFFMPEG(MediaPacket packet,const UCHAR* buffer,UINT *samplepos);\r
- int AllocateCodecsFFMPEG();\r
- int DeAllocateCodecsFFMPEG();\r
- int DecodePacketFFMPEG();\r
- bool ffmpeg_running;\r
- bool ffmpeg_hastime; // signals if a pts is now\r
- long long ffmpeg_time;\r
+ bool libav_running;\r
+ bool libav_hastime; // signals if a pts is now\r
+ long long libav_time;\r
\r
- int ffwidth,ffheight,ffpixfmt;\r
+ int libavwidth,libavheight,libavpixfmt;\r
\r
\r
#endif\r