[MPlayer-cvslog] r23441 - in trunk: libmpcodecs/img_format.h m_option.c stream/tvi_def.h stream/tvi_v4l2.c
voroshil
subversion at mplayerhq.hu
Fri Jun 1 19:29:36 CEST 2007
Author: voroshil
Date: Fri Jun 1 19:29:35 2007
New Revision: 23441
Log:
mjpeg support for v4l2 tv:// driver
Modified:
trunk/libmpcodecs/img_format.h
trunk/m_option.c
trunk/stream/tvi_def.h
trunk/stream/tvi_v4l2.c
Modified: trunk/libmpcodecs/img_format.h
==============================================================================
--- trunk/libmpcodecs/img_format.h (original)
+++ trunk/libmpcodecs/img_format.h Fri Jun 1 19:29:35 2007
@@ -93,6 +93,7 @@
/* Compressed Formats */
#define IMGFMT_MPEGPES (('M'<<24)|('P'<<16)|('E'<<8)|('S'))
+#define IMGFMT_MJPEG (('M')|('J'<<8)|('P'<<16)|('G'<<24))
/* Formats that are understood by zoran chips, we include
* non-interlaced, interlaced top-first, interlaced bottom-first */
#define IMGFMT_ZRMJPEGNI (('Z'<<24)|('R'<<16)|('N'<<8)|('I'))
Modified: trunk/m_option.c
==============================================================================
--- trunk/m_option.c (original)
+++ trunk/m_option.c Fri Jun 1 19:29:35 2007
@@ -1048,6 +1048,8 @@ static struct {
{"argb", IMGFMT_ARGB},
{"bgra", IMGFMT_BGRA},
{"abgr", IMGFMT_ABGR},
+ {"mjpeg", IMGFMT_MJPEG},
+ {"mjpg", IMGFMT_MJPEG},
{ NULL, 0 }
};
Modified: trunk/stream/tvi_def.h
==============================================================================
--- trunk/stream/tvi_def.h (original)
+++ trunk/stream/tvi_def.h Fri Jun 1 19:29:35 2007
@@ -86,6 +86,12 @@ static inline void fill_blank_frame(char
buffer[i+3]=0;
}
break;
+ case IMGFMT_MJPEG:
+ /*
+ This is compressed format. I don't know yet how to fill such frame with blue color.
+ Keeping frame unchanged.
+ */
+ break;
default:
memset(buffer,0xC0,len);
}
Modified: trunk/stream/tvi_v4l2.c
==============================================================================
--- trunk/stream/tvi_v4l2.c (original)
+++ trunk/stream/tvi_v4l2.c Fri Jun 1 19:29:35 2007
@@ -65,6 +65,13 @@ struct map {
#define BUFFER_COUNT 6
+/** video ringbuffer entry */
+typedef struct {
+ unsigned char *data; ///< frame contents
+ long long timestamp; ///< frame timestamp
+ int framesize; ///< actual frame size
+} video_buffer_entry;
+
/* private data */
typedef struct {
/* video */
@@ -92,8 +99,7 @@ typedef struct {
int video_buffer_size_max;
volatile int video_buffer_size_current;
- unsigned char **video_ringbuffer;
- long long *video_timebuffer;
+ video_buffer_entry *video_ringbuffer;
volatile int video_head;
volatile int video_tail;
volatile int video_cnt;
@@ -185,6 +191,7 @@ static int fcc_mp2vl(int fcc)
case IMGFMT_YUY2: return V4L2_PIX_FMT_YUYV;
case IMGFMT_YV12: return V4L2_PIX_FMT_YVU420;
case IMGFMT_UYVY: return V4L2_PIX_FMT_UYVY;
+ case IMGFMT_MJPEG: return V4L2_PIX_FMT_MJPEG;
}
return fcc;
}
@@ -208,6 +215,7 @@ static int fcc_vl2mp(int fcc)
case V4L2_PIX_FMT_YVU420: return IMGFMT_YV12;
case V4L2_PIX_FMT_YUYV: return IMGFMT_YUY2;
case V4L2_PIX_FMT_UYVY: return IMGFMT_UYVY;
+ case V4L2_PIX_FMT_MJPEG: return IMGFMT_MJPEG;
}
return fcc;
}
@@ -247,6 +255,7 @@ static const char *pixfmt2name(int pixfm
case V4L2_PIX_FMT_YYUV: return "YYUV";
case V4L2_PIX_FMT_HI240: return "HI240";
case V4L2_PIX_FMT_WNVA: return "WNVA";
+ case V4L2_PIX_FMT_MJPEG: return "MJPEG";
}
sprintf(unknown, "unknown (0x%x)", pixfmt);
return unknown;
@@ -909,12 +918,10 @@ static int uninit(priv_t *priv)
if (priv->video_ringbuffer) {
int i;
for (i = 0; i < priv->video_buffer_size_current; i++) {
- free(priv->video_ringbuffer[i]);
+ free(priv->video_ringbuffer[i].data);
}
free(priv->video_ringbuffer);
}
- if (priv->video_timebuffer)
- free(priv->video_timebuffer);
if (!tv_param_noaudio) {
if (priv->audio_ringbuffer)
free(priv->audio_ringbuffer);
@@ -1123,10 +1130,6 @@ static int init(priv_t *priv)
static int get_capture_buffer_size(priv_t *priv)
{
int bufsize, cnt;
- int w = priv->format.fmt.pix.width;
- int h = priv->format.fmt.pix.height;
- int d = pixfmt2depth(priv->format.fmt.pix.pixelformat);
- int bytesperline = w*d/8;
if (tv_param_buffer_size >= 0) {
bufsize = tv_param_buffer_size*1024*1024;
@@ -1145,7 +1148,7 @@ static int get_capture_buffer_size(priv_
#endif
}
- cnt = bufsize/(h*bytesperline);
+ cnt = bufsize/priv->format.fmt.pix.sizeimage;
if (cnt < 2) cnt = 2;
return cnt;
@@ -1228,18 +1231,12 @@ static int start(priv_t *priv)
priv->video_buffer_size_max*priv->format.fmt.pix.height*bytesperline/(1024*1024));
}
- priv->video_ringbuffer = calloc(priv->video_buffer_size_max, sizeof(unsigned char*));
+ priv->video_ringbuffer = calloc(priv->video_buffer_size_max, sizeof(video_buffer_entry));
if (!priv->video_ringbuffer) {
mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate video buffer: %s\n", strerror(errno));
return 0;
}
- for (i = 0; i < priv->video_buffer_size_max; i++)
- priv->video_ringbuffer[i] = NULL;
- priv->video_timebuffer = calloc(priv->video_buffer_size_max, sizeof(long long));
- if (!priv->video_timebuffer) {
- mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate time buffer: %s\n", strerror(errno));
- return 0;
- }
+ memset(priv->video_ringbuffer,0,priv->video_buffer_size_max * sizeof(video_buffer_entry));
pthread_mutex_init(&priv->video_buffer_mutex, NULL);
@@ -1314,24 +1311,20 @@ static int start(priv_t *priv)
}
// copies a video frame
-static inline void copy_frame(priv_t *priv, unsigned char *dest, unsigned char *source)
+static inline void copy_frame(priv_t *priv, video_buffer_entry *dest, unsigned char *source,int len)
{
- int w = priv->format.fmt.pix.width;
- int h = priv->format.fmt.pix.height;
- int d = pixfmt2depth(priv->format.fmt.pix.pixelformat);
- int bytesperline = w*d/8;
-
+ dest->framesize=len;
if(tv_param_automute>0){
if (ioctl(priv->video_fd, VIDIOC_G_TUNER, &priv->tuner) >= 0) {
if(tv_param_automute<<8>priv->tuner.signal){
- fill_blank_frame(dest,bytesperline * h,fcc_vl2mp(priv->format.fmt.pix.pixelformat));
+ fill_blank_frame(dest->data,dest->framesize,fcc_vl2mp(priv->format.fmt.pix.pixelformat));
set_mute(priv,1);
return;
}
}
set_mute(priv,0);
}
- memcpy(dest, source, bytesperline * h);
+ memcpy(dest->data, source, len);
}
// maximum skew change, in frames
@@ -1341,8 +1334,7 @@ static void *video_grabber(void *data)
priv_t *priv = (priv_t*)data;
long long skew, prev_skew, xskew, interval, prev_interval, delta;
int i;
- int framesize = priv->format.fmt.pix.height*priv->format.fmt.pix.width*
- pixfmt2depth(priv->format.fmt.pix.pixelformat)/8;
+ int framesize = priv->format.fmt.pix.sizeimage;
fd_set rdset;
struct timeval timeout;
struct v4l2_buffer buf;
@@ -1478,10 +1470,8 @@ static void *video_grabber(void *data)
unsigned char *newbuf = malloc(framesize);
if (newbuf) {
memmove(priv->video_ringbuffer+priv->video_tail+1, priv->video_ringbuffer+priv->video_tail,
- (priv->video_buffer_size_current-priv->video_tail)*sizeof(unsigned char *));
- memmove(priv->video_timebuffer+priv->video_tail+1, priv->video_timebuffer+priv->video_tail,
- (priv->video_buffer_size_current-priv->video_tail)*sizeof(long long));
- priv->video_ringbuffer[priv->video_tail] = newbuf;
+ (priv->video_buffer_size_current-priv->video_tail)*sizeof(video_buffer_entry));
+ priv->video_ringbuffer[priv->video_tail].data = newbuf;
if ((priv->video_head >= priv->video_tail) && (priv->video_cnt > 0)) priv->video_head++;
priv->video_buffer_size_current++;
}
@@ -1500,23 +1490,22 @@ static void *video_grabber(void *data)
}
} else {
if (priv->immediate_mode) {
- priv->video_timebuffer[priv->video_tail] = 0;
+ priv->video_ringbuffer[priv->video_tail].timestamp = 0;
} else {
// compensate for audio skew
// negative skew => there are more audio samples, increase interval
// positive skew => less samples, shorten the interval
- priv->video_timebuffer[priv->video_tail] = interval - skew;
- if (priv->audio_insert_null_samples && priv->video_timebuffer[priv->video_tail] > 0) {
+ priv->video_ringbuffer[priv->video_tail].timestamp = interval - skew;
+ if (priv->audio_insert_null_samples && priv->video_ringbuffer[priv->video_tail].timestamp > 0) {
pthread_mutex_lock(&priv->audio_mutex);
- priv->video_timebuffer[priv->video_tail] +=
+ priv->video_ringbuffer[priv->video_tail].timestamp +=
(priv->audio_null_blocks_inserted
- priv->dropped_frames_timeshift/priv->audio_usecs_per_block)
*priv->audio_usecs_per_block;
pthread_mutex_unlock(&priv->audio_mutex);
}
}
-
- copy_frame(priv, priv->video_ringbuffer[priv->video_tail], priv->map[buf.index].addr);
+ copy_frame(priv, priv->video_ringbuffer+priv->video_tail, priv->map[buf.index].addr,buf.bytesused);
priv->video_tail = (priv->video_tail+1)%priv->video_buffer_size_current;
priv->video_cnt++;
}
@@ -1546,8 +1535,8 @@ static double grab_video_frame(priv_t *p
}
pthread_mutex_lock(&priv->video_buffer_mutex);
- interval = (double)priv->video_timebuffer[priv->video_head]*1e-6;
- memcpy(buffer, priv->video_ringbuffer[priv->video_head], len);
+ interval = (double)priv->video_ringbuffer[priv->video_head].timestamp*1e-6;
+ memcpy(buffer, priv->video_ringbuffer[priv->video_head].data, len);
priv->video_cnt--;
priv->video_head = (priv->video_head+1)%priv->video_buffer_size_current;
pthread_mutex_unlock(&priv->video_buffer_mutex);
@@ -1557,6 +1546,17 @@ static double grab_video_frame(priv_t *p
static int get_video_framesize(priv_t *priv)
{
+ /*
+ this routine will be called before grab_video_frame
+ thus let's return topmost frame's size
+ */
+ if (priv->video_cnt)
+ return priv->video_ringbuffer[priv->video_head].framesize;
+ /*
+ no video frames yet available. i don't know what to do in this case,
+ thus let's return some fallback result (for compressed format this will be
+ maximum allowed frame size.
+ */
return priv->format.fmt.pix.sizeimage;
}
More information about the MPlayer-cvslog
mailing list