diff options
author | henry <henry@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2003-03-19 16:26:58 +0000 |
---|---|---|
committer | henry <henry@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2003-03-19 16:26:58 +0000 |
commit | 9a1bfa7ec1ef32e1ab316024e93fc6f8f059ce87 (patch) | |
tree | 1dead2dd55c536e477d6470b99a3fa490527cad9 /libmpdemux | |
parent | 391a1c6e729774f965673844fb593a56c55c902e (diff) |
hardware mjpeg encoding using v4l by Iván Szántó <szivan@freemail.hu>
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@9621 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmpdemux')
-rw-r--r-- | libmpdemux/tv.c | 24 | ||||
-rw-r--r-- | libmpdemux/tv.h | 3 | ||||
-rw-r--r-- | libmpdemux/tvi_v4l.c | 165 |
3 files changed, 191 insertions, 1 deletions
diff --git a/libmpdemux/tv.c b/libmpdemux/tv.c index a4b5404597..2f4681f205 100644 --- a/libmpdemux/tv.c +++ b/libmpdemux/tv.c @@ -63,6 +63,9 @@ int tv_param_balance = -1; 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 @@ static int open_tv(tvi_handle_t *tvh) 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) diff --git a/libmpdemux/tv.h b/libmpdemux/tv.h index abd5055021..0ad4680833 100644 --- a/libmpdemux/tv.h +++ b/libmpdemux/tv.h @@ -34,6 +34,9 @@ extern int tv_param_balance; 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 diff --git a/libmpdemux/tvi_v4l.c b/libmpdemux/tvi_v4l.c index 21d630fe4b..c9712dbd99 100644 --- a/libmpdemux/tvi_v4l.c +++ b/libmpdemux/tvi_v4l.c @@ -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 @@ typedef struct { long long audio_skew_total; long audio_recv_blocks_total; long audio_sent_blocks_total; + long mjpeg_bufsize; } priv_t; @@ -443,8 +448,97 @@ static int init(priv_t *priv) priv->capability.maxwidth, priv->capability.maxheight); priv->width = priv->capability.minwidth; priv->height = priv->capability.minheight; - mp_msg(MSGT_TV, MSGL_INFO, " Inputs: %d\n", priv->capability.channels); + /* 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 @@ static int init(priv_t *priv) goto err; } + if ( !tv_param_mjpeg ) + { /* map grab buffer */ if (ioctl(priv->video_fd, VIDIOCGMBUF, &priv->mbuf) == -1) { @@ -500,6 +596,7 @@ static int init(priv_t *priv) 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 @@ err: 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 @@ static int uninit(priv_t *priv) 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 @@ static int start(priv_t *priv) return(0); } + if ( !tv_param_mjpeg ) + { priv->nbuf = priv->mbuf.frames; for (i=0; i < priv->nbuf; i++) { @@ -669,6 +777,7 @@ static int start(priv_t *priv) 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 @@ static int control(priv_t *priv, int cmd, void *arg) 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 @@ static void *video_grabber(void *data) 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 @@ static void *video_grabber(void *data) 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 @@ static void *video_grabber(void *data) 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; } |