|
From: libvidcap c. m. <lib...@li...> - 2007-10-12 16:30:12
|
Revision: 46
http://libvidcap.svn.sourceforge.net/libvidcap/?rev=46&view=rev
Author: bcholew
Date: 2007-10-12 09:30:09 -0700 (Fri, 12 Oct 2007)
Log Message:
-----------
Add generic support for images with strides. Make Mac version stride-aware. Keep linux and Windows builds stride-ignorant.
Modified Paths:
--------------
trunk/src/conv.c
trunk/src/conv.h
trunk/src/directshow/SourceStateMachine.cpp
trunk/src/sapi.c
trunk/src/sapi.h
trunk/src/sapi_context.h
trunk/src/sapi_qt.c
trunk/src/sapi_v4l.c
trunk/src/vidcap.c
Modified: trunk/src/conv.c
===================================================================
--- trunk/src/conv.c 2007-10-10 18:31:30 UTC (rev 45)
+++ trunk/src/conv.c 2007-10-12 16:30:09 UTC (rev 46)
@@ -23,7 +23,9 @@
*
*/
+#include "string.h"
#include "conv.h"
+#include "logging.h"
int conv_2vuy_to_i420(int w, int h, const char * s, char * d);
int conv_2vuy_to_yuy2(int w, int h, const char * s, char * d);
@@ -69,6 +71,150 @@
static const int conv_list_len = sizeof(conv_list) / sizeof(struct conv_info);
+static int
+destride_packed(int image_byte_width, int height, signed int stride,
+ const char * src, char * dst)
+{
+ /* destride a packed structure */
+ char * dst_even = dst;
+ char * dst_odd = dst + image_byte_width;
+ const char * src_even = src;
+ const char * src_odd = src + stride;
+
+ int i;
+ for ( i = 0; i < height / 2; ++i )
+ {
+ memcpy(dst_even, src_even, image_byte_width);
+ memcpy(dst_odd, src_odd, image_byte_width);
+
+ dst_even += 2 * image_byte_width;
+ dst_odd += 2 * image_byte_width;
+ src_even += 2 * stride;
+ src_odd += 2 * stride;
+ }
+
+ return 0;
+}
+
+static int
+destride_planar(int width, int height,
+ int u_width, int u_height,
+ int v_width, int v_height,
+ signed int y_stride, signed int u_stride, signed int v_stride,
+ const char * src, char * dst)
+{
+ char * dst_y_even = dst;
+ char * dst_y_odd = dst + width;
+ char * dst_u_even = dst + width * height;
+ char * dst_u_odd = dst_u_even + u_width;
+ char * dst_v_even = dst_u_even + u_width * u_height;
+ char * dst_v_odd = dst_v_even + v_width;
+ const char * src_y_even = src;
+ const char * src_y_odd = src + y_stride;
+ const char * src_u_even = src + y_stride * height;
+ const char * src_u_odd = src_u_even + u_stride;
+ const char * src_v_even = src_u_even + u_stride * u_height;
+ const char * src_v_odd = src_v_even + v_stride;
+
+ int i;
+
+ for ( i = 0; i < height / 2; ++i )
+ {
+ memcpy(dst_y_even, src_y_even, width);
+ memcpy(dst_y_odd, src_y_odd, width);
+
+ dst_y_even += 2 * width;
+ dst_y_odd += 2 * width;
+ src_y_even += 2 * y_stride;
+ src_y_odd += 2 * y_stride;
+ }
+
+ for ( i = 0; i < u_height / 2; ++i )
+ {
+ memcpy(dst_u_even, src_u_even, u_width);
+ memcpy(dst_u_odd, src_u_odd, u_width);
+
+ dst_u_even += 2 * u_width;
+ dst_u_odd += 2 * u_width;
+ src_u_even += 2 * u_stride;
+ src_u_odd += 2 * u_stride;
+ }
+
+ for ( i = 0; i < v_height / 2; ++i )
+ {
+ memcpy(dst_v_even, src_v_even, v_width);
+ memcpy(dst_v_odd, src_v_odd, v_width);
+
+ dst_v_even += 2 * v_width;
+ dst_v_odd += 2 * v_width;
+ src_v_even += 2 * v_stride;
+ src_v_odd += 2 * v_stride;
+ }
+
+ return 0;
+}
+
+int
+destridify(int width, int height, int fourcc, int stride,
+ const char * src, char * dst)
+{
+ /* NOTE: we're making-up the u and v strides for planar formats,
+ * rather than pass them in.
+ */
+
+ switch ( fourcc )
+ {
+ case VIDCAP_FOURCC_I420:
+ log_error("UNTESTED: destriding i420\n");
+ /* FIXME: only destride if necessary */
+ return destride_planar(width, height,
+ /* fix these u and v strides to be 32-bit aligned? */
+ width / 2, height / 2, width / 2, height / 2,
+ stride, stride / 2, stride / 2,
+ src, dst);
+ break;
+ case VIDCAP_FOURCC_YUY2:
+ if ( stride == 2 * width )
+ return -1;
+ return destride_packed(2 * width, height, stride, src, dst);
+ break;
+ case VIDCAP_FOURCC_RGB32:
+ if ( stride == 4 * width )
+ return -1;
+ return destride_packed(4 * width, height, stride, src, dst);
+ break;
+ case VIDCAP_FOURCC_2VUY:
+ if ( stride == 2 * width )
+ return -1;
+ return destride_packed(2 * width, height, stride, src, dst);
+ break;
+ case VIDCAP_FOURCC_RGB24:
+ if ( stride == 3 * width )
+ return -1;
+ return destride_packed(3 * width, height, stride, src, dst);
+ break;
+ case VIDCAP_FOURCC_BOTTOM_UP_RGB24:
+ if ( stride == 3 * width )
+ return -1;
+ return destride_packed(3 * width, height, stride, src, dst);
+ break;
+ case VIDCAP_FOURCC_YVU9:
+ log_error("UNTESTED: destriding yvu9\n");
+ /* FIXME: only destride if necessary */
+ return destride_planar(width, height,
+ width / 4, height / 4, width / 4, height / 4,
+ /* fix u and v strides to be 32-bit aligned? */
+ stride, stride / 4, stride / 4,
+ src, dst);
+ break;
+ default:
+ log_error("Invalid fourcc [%s]\n",
+ vidcap_fourcc_string_get(fourcc));
+ return -1;
+ break;
+ }
+}
+
conv_func
conv_conversion_func_get(int src_fourcc, int dst_fourcc)
{
Modified: trunk/src/conv.h
===================================================================
--- trunk/src/conv.h 2007-10-10 18:31:30 UTC (rev 45)
+++ trunk/src/conv.h 2007-10-12 16:30:09 UTC (rev 46)
@@ -53,6 +53,10 @@
const char *
conv_conversion_name_get(conv_func function);
+int
+destridify(int width, int height, int fourcc, int stride,
+ const char * src, char * dst);
+
#ifdef __cplusplus
}
#endif
Modified: trunk/src/directshow/SourceStateMachine.cpp
===================================================================
--- trunk/src/directshow/SourceStateMachine.cpp 2007-10-10 18:31:30 UTC (rev 45)
+++ trunk/src/directshow/SourceStateMachine.cpp 2007-10-12 16:30:09 UTC (rev 46)
@@ -367,7 +367,7 @@
okToSendStart_ = true;
// final capture callback - with error status
- sapi_src_capture_notify(sourceContext_, 0, 0, -1);
+ sapi_src_capture_notify(sourceContext_, 0, 0, 0, -1);
}
else
{
@@ -469,7 +469,7 @@
Sleep(10);
// final capture callback - with error status
- sapi_src_capture_notify(sourceContext_, 0, 0, -1);
+ sapi_src_capture_notify(sourceContext_, 0, 0, 0, -1);
}
}
@@ -496,7 +496,7 @@
src_->stop();
// final capture callback - with error status
- sapi_src_capture_notify(sourceContext_, 0, 0, -1);
+ sapi_src_capture_notify(sourceContext_, 0, 0, 0, -1);
callbackCancellationInProgress_ = false;
}
@@ -519,7 +519,7 @@
int ret = sapi_src_capture_notify(instance->sourceContext_,
reinterpret_cast<const char *>(pBuff),
- static_cast<int>(buffSize), 0);
+ static_cast<int>(buffSize), 0, 0);
instance->callbackInProgress_ = false;
Modified: trunk/src/sapi.c
===================================================================
--- trunk/src/sapi.c 2007-10-10 18:31:30 UTC (rev 45)
+++ trunk/src/sapi.c 2007-10-12 16:30:09 UTC (rev 46)
@@ -216,9 +216,11 @@
return 0;
}
+/* NOTE: stride-ignorant sapis should pass a stride of zero */
int
sapi_src_capture_notify(struct sapi_src_context * src_ctx,
const char * video_data, int video_data_size,
+ signed int stride,
int error_status)
{
struct vidcap_capture_info cap_info;
@@ -229,6 +231,8 @@
*/
vidcap_src_capture_callback cap_callback = src_ctx->capture_callback;
void * cap_data = src_ctx->capture_data;
+ void * buf = 0;
+ int buf_data_size = 0;
int send_frame = 0;
@@ -240,6 +244,23 @@
cap_info.error_status = error_status;
+ if ( !cap_info.error_status && stride &&
+ !destridify(src_ctx->fmt_native.width,
+ src_ctx->fmt_native.height,
+ src_ctx->fmt_native.fourcc,
+ stride,
+ video_data,
+ src_ctx->stride_free_buf) )
+ {
+ buf = src_ctx->stride_free_buf;
+ buf_data_size = src_ctx->stride_free_buf_size;
+ }
+ else
+ {
+ buf = (void *)video_data;
+ buf_data_size = video_data_size;
+ }
+
if ( cap_info.error_status )
{
cap_info.video_data = 0;
@@ -248,9 +269,9 @@
else if ( src_ctx->fmt_conv_func )
{
if ( src_ctx->fmt_conv_func(
- src_ctx->fmt_nominal.width,
- src_ctx->fmt_nominal.height,
- video_data,
+ src_ctx->fmt_native.width,
+ src_ctx->fmt_native.height,
+ buf,
src_ctx->fmt_conv_buf) )
{
log_error("failed format conversion\n");
@@ -262,8 +283,8 @@
}
else
{
- cap_info.video_data = video_data;
- cap_info.video_data_size = video_data_size;
+ cap_info.video_data = buf;
+ cap_info.video_data_size = buf_data_size;
}
if ( ( send_frame || error_status ) && cap_callback && cap_data != VIDCAP_INVALID_USER_DATA )
Modified: trunk/src/sapi.h
===================================================================
--- trunk/src/sapi.h 2007-10-10 18:31:30 UTC (rev 45)
+++ trunk/src/sapi.h 2007-10-12 16:30:09 UTC (rev 46)
@@ -47,6 +47,7 @@
int
sapi_src_capture_notify(struct sapi_src_context * src_ctx,
const char * video_data, int video_data_size,
+ signed int stride,
int error_status);
int
Modified: trunk/src/sapi_context.h
===================================================================
--- trunk/src/sapi_context.h 2007-10-10 18:31:30 UTC (rev 45)
+++ trunk/src/sapi_context.h 2007-10-12 16:30:09 UTC (rev 46)
@@ -71,6 +71,9 @@
char * fmt_conv_buf;
int fmt_conv_buf_size;
+ char * stride_free_buf;
+ int stride_free_buf_size;
+
struct vidcap_fmt_info * fmt_list;
int fmt_list_len;
Modified: trunk/src/sapi_qt.c
===================================================================
--- trunk/src/sapi_qt.c 2007-10-10 18:31:30 UTC (rev 45)
+++ trunk/src/sapi_qt.c 2007-10-12 16:30:09 UTC (rev 46)
@@ -215,7 +215,8 @@
sapi_src_capture_notify(src_ctx,
CVPixelBufferGetBaseAddress(pixel_buffer),
- CVPixelBufferGetDataSize(pixel_buffer), 0);
+ CVPixelBufferGetDataSize(pixel_buffer),
+ CVPixelBufferGetBytesPerRow(pixel_buffer), 0);
if ( (err = CVPixelBufferUnlockBaseAddress(pixel_buffer, 0)) )
{
@@ -425,7 +426,7 @@
if ( sg_source_capture_poll(qt_src_ctx->src) )
{
- sapi_src_capture_notify(src_ctx, 0, 0, -1);
+ sapi_src_capture_notify(src_ctx, 0, 0, 0, -1);
ret = -1;
goto bail;
}
Modified: trunk/src/sapi_v4l.c
===================================================================
--- trunk/src/sapi_v4l.c 2007-10-10 18:31:30 UTC (rev 45)
+++ trunk/src/sapi_v4l.c 2007-10-12 16:30:09 UTC (rev 46)
@@ -352,6 +352,7 @@
sapi_src_capture_notify(src_ctx, fb_base +
v4l_src_ctx->mbuf.offsets[capture_frame],
capture_size,
+ 0,
0);
++capture_frame_count;
Modified: trunk/src/vidcap.c
===================================================================
--- trunk/src/vidcap.c 2007-10-10 18:31:30 UTC (rev 45)
+++ trunk/src/vidcap.c 2007-10-12 16:30:09 UTC (rev 46)
@@ -356,6 +356,9 @@
if ( src_ctx->fmt_conv_buf )
free(src_ctx->fmt_conv_buf);
+ if ( src_ctx->stride_free_buf )
+ free(src_ctx->stride_free_buf);
+
if ( src_ctx->frame_times )
sliding_window_destroy(src_ctx->frame_times);
@@ -420,6 +423,32 @@
src_ctx->fmt_native.fourcc,
src_ctx->fmt_nominal.fourcc);
+ if ( src_ctx->stride_free_buf )
+ {
+ free(src_ctx->stride_free_buf);
+ src_ctx->stride_free_buf = 0;
+ }
+
+ src_ctx->stride_free_buf_size = conv_fmt_size_get(
+ src_ctx->fmt_native.width,
+ src_ctx->fmt_native.height,
+ src_ctx->fmt_native.fourcc);
+
+ if ( !src_ctx->stride_free_buf_size )
+ {
+ log_error("failed to get stride-free buffer size for %s\n",
+ vidcap_fourcc_string_get(
+ fmt_info->fourcc));
+ return -1;
+ }
+
+ if ( !(src_ctx->stride_free_buf =
+ malloc(src_ctx->stride_free_buf_size)) )
+ {
+ log_oom(__FILE__, __LINE__);
+ return -1;
+ }
+
if ( src_ctx->fmt_conv_buf )
{
free(src_ctx->fmt_conv_buf);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|