Mercurial > mplayer.hg
changeset 9620:ce4cd85498f3
hardware mjpeg encoding using v4l by IvŹ«ˇn SzŹ«ˇntŹ«Ń <szivan@freemail.hu>
author | henry |
---|---|
date | Wed, 19 Mar 2003 16:26:58 +0000 |
parents | 38ab6f87fef4 |
children | 3ef467aac4a1 |
files | DOCS/en/mplayer.1 cfg-common.h libmpdemux/tv.c libmpdemux/tv.h libmpdemux/tvi_v4l.c |
diffstat | 5 files changed, 219 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/DOCS/en/mplayer.1 Wed Mar 19 15:28:11 2003 +0000 +++ b/DOCS/en/mplayer.1 Wed Mar 19 16:26:58 2003 +0000 @@ -787,6 +787,31 @@ (default for mencoder). A value of 1 (default for mplayer) means to do video capture only and let the audio go through a loopback cable from the TV card to the soundcard. +.IPs mjpeg +Use hardware mjpeg compression (if the card supports it). +When using this option, you do not need to specify the width and height +of the output window, because mplayer will determine it automatically +from the decimation value (see below). +.IPs decimation=<1,2,4> +choose the size of the picture that will be compressed by hardware +mjpeg compression: +.RSss +1: full size + 704x576 PAL + 704x480 NTSC +.br +2: medium size + 352x288 PAL + 352x240 NTSC +.br +4: small size + 176x144 PAL + 176x120 NTSC +.REss +.IPs quality=<0-100> +choose the quality of the jpeg compression +.br +(quality < 60 recommended for full size) .RE . .TP
--- a/cfg-common.h Wed Mar 19 15:28:11 2003 +0000 +++ b/cfg-common.h Wed Mar 19 16:26:58 2003 +0000 @@ -286,6 +286,9 @@ {"forcechan", &tv_param_forcechan, CONF_TYPE_INT, CONF_RANGE, 1, 2, NULL}, {"forceaudio", &tv_param_force_audio, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"buffersize", &tv_param_buffer_size, CONF_TYPE_INT, CONF_RANGE, 16, 1024, NULL}, + {"mjpeg", &tv_param_mjpeg, CONF_TYPE_FLAG, 0, 0, 1, NULL}, + {"decimation", &tv_param_decimation, CONF_TYPE_INT, CONF_RANGE, 1, 4, NULL}, + {"quality", &tv_param_quality, CONF_TYPE_INT, CONF_RANGE, 0, 100, NULL}, #ifdef HAVE_ALSA9 {"alsa", &tv_param_alsa, CONF_TYPE_FLAG, 0, 0, 1, NULL}, #endif
--- a/libmpdemux/tv.c Wed Mar 19 15:28:11 2003 +0000 +++ b/libmpdemux/tv.c Wed Mar 19 16:26:58 2003 +0000 @@ -63,6 +63,9 @@ int tv_param_forcechan = -1; int tv_param_force_audio = 0; int tv_param_buffer_size = -1; +int tv_param_mjpeg = 0; +int tv_param_decimation = 2; +int tv_param_quality = 90; #ifdef HAVE_ALSA9 int tv_param_alsa = 0; #endif @@ -179,6 +182,27 @@ return 0; } + +#ifdef HAVE_TV_V4L + if ( tv_param_mjpeg ) + { + /* set width to expected value */ + if (tv_param_width == -1) + { + tv_param_width = 704/tv_param_decimation; + } + if (tv_param_height == -1) + { + if ( tvh->norm != TV_NORM_NTSC ) + tv_param_height = 576/tv_param_decimation; + else + tv_param_height = 480/tv_param_decimation; + } + mp_msg(MSGT_TV, MSGL_INFO, + " MJP: width %d height %d\n", tv_param_width, tv_param_height); + } +#endif + /* limits on w&h are norm-dependent -- JM */ /* set width */ if (tv_param_width != -1)
--- a/libmpdemux/tv.h Wed Mar 19 15:28:11 2003 +0000 +++ b/libmpdemux/tv.h Wed Mar 19 16:26:58 2003 +0000 @@ -34,6 +34,9 @@ extern int tv_param_forcechan; extern int tv_param_force_audio; extern int tv_param_buffer_size; +extern int tv_param_mjpeg; +extern int tv_param_decimation; +extern int tv_param_quality; #ifdef HAVE_ALSA9 extern int tv_param_alsa; #endif
--- a/libmpdemux/tvi_v4l.c Wed Mar 19 15:28:11 2003 +0000 +++ b/libmpdemux/tvi_v4l.c Wed Mar 19 16:26:58 2003 +0000 @@ -9,6 +9,9 @@ Multithreading, a/v sync and native ALSA support by Jindrich Makovicka <makovick@kmlinux.fjfi.cvut.cz> + Mjpeg hardware encoding support by + Iván Szántó <szivan@freemail.hu> + CODE IS UNDER DEVELOPMENT, NO FEATURE REQUESTS PLEASE! */ @@ -37,6 +40,7 @@ #include "../libao2/afmt.h" #include "../libvo/img_format.h" #include "../libvo/fastmemcpy.h" +#include "../libvo/videodev_mjpeg.h" #include "tv.h" @@ -132,6 +136,7 @@ long long audio_skew_total; long audio_recv_blocks_total; long audio_sent_blocks_total; + long mjpeg_bufsize; } priv_t; @@ -443,8 +448,97 @@ priv->capability.maxwidth, priv->capability.maxheight); priv->width = priv->capability.minwidth; priv->height = priv->capability.minheight; + + /* somewhere here could disable tv_param_mjpeg, if it is not a capability */ + + /* initialize if necessary */ + if ( tv_param_mjpeg ) + { + struct mjpeg_params bparm; + struct mjpeg_requestbuffers breq; /* buffer requests */ + + if (ioctl(priv->video_fd, MJPIOC_G_PARAMS, &bparm) < 0) + { + mp_msg(MSGT_TV, MSGL_ERR, + " MJP: Error getting video parameters: %s\n", sys_errlist[errno]); + goto err; + } + + mp_msg(MSGT_TV, MSGL_INFO, + " MJP: previous params: x: %d, y: %d, w: %d, h: %d, decim: %d, fields: %d,\n", + bparm.img_x, bparm.img_y, bparm.img_width, bparm.img_height, + bparm.decimation, bparm.field_per_buff); + + mp_msg(MSGT_TV, MSGL_INFO, + " MJP: HorDcm: %d, VerDcm: %d, TmpDcm: %d\n", + bparm.HorDcm, bparm.VerDcm, bparm.TmpDcm); + + bparm.input = tv_param_input; /* tv */ + if (!strcasecmp(tv_param_norm, "pal")) + bparm.norm = 0; /* PAL */ + else if (!strcasecmp(tv_param_norm, "ntsc")) + bparm.norm = 1; /* NTSC */ + else if (!strcasecmp(tv_param_norm, "secam")) + bparm.norm = 2; /* SECAM */ + bparm.quality = tv_param_quality; + bparm.decimation = tv_param_decimation; + + mp_msg(MSGT_TV, MSGL_INFO, " MJP: setting params to decimation: %d, quality: %d\n", + bparm.decimation, bparm.quality); + + if (ioctl(priv->video_fd, MJPIOC_S_PARAMS, &bparm) < 0) + { + mp_msg(MSGT_TV, MSGL_ERR, + " MJP: Error setting video parameters: %s\n", sys_errlist[errno]); + goto err; + } + + if (ioctl(priv->video_fd, MJPIOC_G_PARAMS, &bparm) < 0) + { + mp_msg(MSGT_TV, MSGL_ERR, + " MJP: Error getting video parameters: %s\n", sys_errlist[errno]); + goto err; + } + + mp_msg(MSGT_TV, MSGL_INFO, + " MJP: current params: x: %d, y: %d, w: %d, h: %d, decim: %d, fields: %d,\n", + bparm.img_x, bparm.img_y, bparm.img_width, bparm.img_height, + bparm.decimation, bparm.field_per_buff); + + mp_msg(MSGT_TV, MSGL_INFO, + " MJP: HorDcm: %d, VerDcm: %d, TmpDcm: %d\n", + bparm.HorDcm, bparm.VerDcm, bparm.TmpDcm); + + + breq.count = 64; + priv -> nbuf = breq.count; + priv->mbuf.frames = priv -> nbuf; + priv->mjpeg_bufsize = 256*1024; + if (tv_param_buffer_size >= 0) { + priv->mjpeg_bufsize = tv_param_buffer_size*1024; + } + breq.size = priv -> mjpeg_bufsize; + if (ioctl(priv->video_fd, MJPIOC_REQBUFS,&(breq)) < 0) + { + mp_msg (MSGT_TV, MSGL_ERR, + " MJP: Error requesting video buffers: %s\n", sys_errlist[errno]); + goto err; + } + mp_msg(MSGT_TV, MSGL_INFO, + " MJP: Got %ld buffers of size %ld KB\n", + breq.count, breq.size/1024); + + priv -> mmap = mmap(0, breq.count * breq.size, + PROT_READ|PROT_WRITE, MAP_SHARED, priv->video_fd, 0); + if (priv -> mmap == MAP_FAILED) + { + mp_msg(MSGT_TV, MSGL_INFO, + " MJP: Error mapping video buffers: %s\n", sys_errlist[errno]); + goto err; + } + } + mp_msg(MSGT_TV, MSGL_INFO, " Inputs: %d\n", priv->capability.channels); - priv->channels = (struct video_channel *)malloc(sizeof(struct video_channel)*priv->capability.channels); if (!priv->channels) goto malloc_failed; @@ -474,6 +568,8 @@ goto err; } + if ( !tv_param_mjpeg ) + { /* map grab buffer */ if (ioctl(priv->video_fd, VIDIOCGMBUF, &priv->mbuf) == -1) { @@ -500,6 +596,7 @@ if (!priv->buf) goto malloc_failed; memset(priv->buf, 0, priv->nbuf * sizeof(struct video_mmap)); + } /* init v4l audio even when we don't capture */ init_v4l_audio(priv); @@ -555,6 +652,7 @@ static int uninit(priv_t *priv) { + unsigned long num; priv->shutdown = 1; mp_msg(MSGT_TV, MSGL_V, "Waiting for threads to finish... "); @@ -573,6 +671,14 @@ ioctl(priv->video_fd, VIDIOCSAUDIO, &priv->audio[priv->audio_id]); } + if ( tv_param_mjpeg ) + { + num = -1; + if (ioctl(priv->video_fd, MJPIOC_QBUF_CAPT, &num) < 0) + { + mp_msg(MSGT_TV, MSGL_ERR, "\n MJP: ioctl MJPIOC_QBUF_CAPT failed: %s\n", strerror(errno)); + } + } close(priv->video_fd); audio_in_uninit(&priv->audio_in); @@ -660,6 +766,8 @@ return(0); } + if ( !tv_param_mjpeg ) + { priv->nbuf = priv->mbuf.frames; for (i=0; i < priv->nbuf; i++) { @@ -669,6 +777,7 @@ priv->buf[i].height = priv->height; mp_msg(MSGT_TV, MSGL_DBG2, "buffer: %d => %p\n", i, &priv->buf[i]); } + } #if 0 { @@ -853,8 +962,19 @@ int output_fmt = -1; output_fmt = priv->format; + if ( tv_param_mjpeg ) + { + mp_msg(MSGT_TV, MSGL_INFO, " MJP: setting sh_video->format to mjpg\n"); + output_fmt = 0x47504a4d; + output_fmt = 0x67706a6d; + (int)*(void **)arg = output_fmt; + mp_msg(MSGT_TV, MSGL_V, "Output format: %s\n", "mjpg"); + } + else + { (int)*(void **)arg = output_fmt; mp_msg(MSGT_TV, MSGL_V, "Output format: %s\n", vo_format_name(output_fmt)); + } return(TVI_CONTROL_TRUE); } case TVI_CONTROL_VID_SET_FORMAT: @@ -1263,14 +1383,30 @@ int i; int framecount; int tolerance; + unsigned long num; /* start the capture process */ + if ( tv_param_mjpeg ) + { + mp_msg(MSGT_TV, MSGL_INFO, " MJP: gonna capture ! \n"); + for (i=0; i < priv->nbuf; i++) { + num = i; + if (ioctl(priv->video_fd, MJPIOC_QBUF_CAPT, &num) < 0) + { + mp_msg(MSGT_TV, MSGL_ERR, + "\n MJP: ioctl MJPIOC_QBUF_CAPT b failed: %s\n", strerror(errno)); + } + } + } + else + { for (i=0; i < priv->nbuf; i++) { if (ioctl(priv->video_fd, VIDIOCMCAPTURE, &priv->buf[i]) == -1) { mp_msg(MSGT_TV, MSGL_ERR, "\nioctl mcapture failed: %s\n", strerror(errno)); } + } } gettimeofday(&curtime, NULL); @@ -1301,8 +1437,17 @@ frame = i; + if ( tv_param_mjpeg ) + { + while (ioctl(priv->video_fd, MJPIOC_SYNC, &priv->buf[frame].frame) < 0 && + (errno == EAGAIN || errno == EINTR)); + + } + else + { while (ioctl(priv->video_fd, VIDIOCSYNC, &priv->buf[frame].frame) < 0 && (errno == EAGAIN || errno == EINTR)); + } mp_dbg(MSGT_TV, MSGL_DBG3, "\npicture sync failed\n"); gettimeofday(&curtime, NULL); @@ -1405,20 +1550,38 @@ priv->video_timebuffer[priv->video_tail] = interval - skew; } + if ( tv_param_mjpeg ) + copy_frame(priv, priv->video_ringbuffer[priv->video_tail], + priv->mmap+(priv->mjpeg_bufsize)*i); + else copy_frame(priv, priv->video_ringbuffer[priv->video_tail], priv->mmap+priv->mbuf.offsets[frame]); priv->video_tail = (priv->video_tail+1)%priv->video_buffer_size_current; priv->video_cnt++; } + if ( tv_param_mjpeg ) + { + num = frame; + if (ioctl(priv->video_fd, MJPIOC_QBUF_CAPT, &num) < 0) + { + mp_msg(MSGT_TV, MSGL_ERR, "\n MJP: ioctl MJPIOC_QBUF_CAPT end failed: %s\n", + strerror(errno)); + continue; + } + } + else + { if (ioctl(priv->video_fd, VIDIOCMCAPTURE, &priv->buf[frame]) == -1) { mp_msg(MSGT_TV, MSGL_ERR, "\nioctl mcapture failed: %s\n", strerror(errno)); continue; } + } } } + mp_msg(MSGT_TV, MSGL_INFO, " MJP: returning! \n"); return NULL; }