Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mediastreamer2
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
3
Merge Requests
3
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
External Wiki
External Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
BC
public
mediastreamer2
Commits
2841874a
Commit
2841874a
authored
Oct 10, 2011
by
Pierre-Eric Pelloux-Prayer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
video function improvements (neon scaling)
parent
add023bd
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
450 additions
and
323 deletions
+450
-323
msvideo.h
include/mediastreamer2/msvideo.h
+9
-0
msandroidvideo.cpp
src/msandroidvideo.cpp
+17
-11
msvideo.c
src/msvideo.c
+41
-26
msvideo_neon.c
src/msvideo_neon.c
+370
-273
videostream.c
src/videostream.c
+13
-13
No files found.
include/mediastreamer2/msvideo.h
View file @
2841874a
...
...
@@ -50,9 +50,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MS_VIDEO_SIZE_QQVGA_W 160
#define MS_VIDEO_SIZE_QQVGA_H 120
#define MS_VIDEO_SIZE_HQVGA_W 160
#define MS_VIDEO_SIZE_HQVGA_H 240
#define MS_VIDEO_SIZE_QVGA_W 320
#define MS_VIDEO_SIZE_QVGA_H 240
#define MS_VIDEO_SIZE_HVGA_W 320
#define MS_VIDEO_SIZE_HVGA_H 480
#define MS_VIDEO_SIZE_VGA_W 640
#define MS_VIDEO_SIZE_VGA_H 480
...
...
@@ -223,6 +229,9 @@ MS2_PUBLIC void rotate_plane_neon_clockwise(int wDest, int hDest, int full_width
MS2_PUBLIC
void
rotate_plane_neon_anticlockwise
(
int
wDest
,
int
hDest
,
int
full_width
,
uint8_t
*
src
,
uint8_t
*
dst
);
MS2_PUBLIC
void
rotate_cbcr_to_cr_cb
(
int
wDest
,
int
hDest
,
int
full_width
,
uint8_t
*
cbcr_src
,
uint8_t
*
cr_dst
,
uint8_t
*
cb_dst
,
bool_t
clockWise
);
MS2_PUBLIC
void
deinterlace_and_rotate_180_neon
(
uint8_t
*
ysrc
,
uint8_t
*
cbcrsrc
,
uint8_t
*
ydst
,
uint8_t
*
udst
,
uint8_t
*
vdst
,
int
w
,
int
h
,
int
y_byte_per_row
,
int
cbcr_byte_per_row
);
void
deinterlace_down_scale_and_rotate_180_neon
(
uint8_t
*
ysrc
,
uint8_t
*
cbcrsrc
,
uint8_t
*
ydst
,
uint8_t
*
udst
,
uint8_t
*
vdst
,
int
w
,
int
h
,
int
y_byte_per_row
,
int
cbcr_byte_per_row
,
bool_t
down_scale
);
void
deinterlace_down_scale_neon
(
uint8_t
*
ysrc
,
uint8_t
*
cbcrsrc
,
uint8_t
*
ydst
,
uint8_t
*
u_dst
,
uint8_t
*
v_dst
,
int
w
,
int
h
,
int
y_byte_per_row
,
int
cbcr_byte_per_row
,
bool_t
down_scale
);
mblk_t
*
copy_ycbcrbiplanar_to_true_yuv_with_rotation_and_down_scale_by_2
(
uint8_t
*
y
,
uint8_t
*
cbcr
,
int
rotation
,
int
w
,
int
h
,
int
y_byte_per_row
,
int
cbcr_byte_per_row
,
bool_t
uFirstvSecond
,
bool_t
down_scale
);
#endif
static
inline
bool_t
ms_video_size_greater_than
(
MSVideoSize
vs1
,
MSVideoSize
vs2
){
...
...
src/msandroidvideo.cpp
View file @
2841874a
...
...
@@ -78,6 +78,7 @@ struct AndroidReaderContext {
MSVideoSize
requestedSize
,
hwCapableSize
;
ms_mutex_t
mutex
;
int
rotation
,
rotationSavedDuringVSize
;
int
useDownscaling
;
jobject
androidCamera
;
jobject
previewWindow
;
...
...
@@ -135,25 +136,29 @@ static int video_capture_set_vsize(MSFilter *f, void* data){
// handle result :
// - 0 : width
// - 1 : height
jint
res
[
2
];
env
->
GetIntArrayRegion
((
jintArray
)
resArray
,
0
,
2
,
res
);
ms_message
(
"Camera selected resolution is: %dx%d (requested: %dx%d)
\n
"
,
res
[
0
],
res
[
1
],
d
->
requestedSize
.
width
,
d
->
requestedSize
.
height
);
// - 2 : useDownscaling
jint
res
[
3
];
env
->
GetIntArrayRegion
((
jintArray
)
resArray
,
0
,
3
,
res
);
ms_message
(
"Camera selected resolution is: %dx%d (requested: %dx%d) with downscaling?%d
\n
"
,
res
[
0
],
res
[
1
],
d
->
requestedSize
.
width
,
d
->
requestedSize
.
height
,
res
[
2
]);
d
->
hwCapableSize
.
width
=
res
[
0
];
d
->
hwCapableSize
.
height
=
res
[
1
];
d
->
useDownscaling
=
res
[
2
];
int
rqSize
=
d
->
requestedSize
.
width
*
d
->
requestedSize
.
height
;
int
hwSize
=
d
->
hwCapableSize
.
width
*
d
->
hwCapableSize
.
height
;
double
downscale
=
d
->
useDownscaling
?
0.5
:
1
;
// if hw supplies a smaller resolution, modify requested size accordingly
if
(
hwSize
<
rqSize
)
{
if
(
(
hwSize
*
downscale
*
downscale
)
<
rqSize
)
{
ms_message
(
"Camera cannot produce requested resolution %dx%d, will supply smaller one: %dx%d
\n
"
,
d
->
requestedSize
.
width
,
d
->
requestedSize
.
height
,
res
[
0
],
res
[
1
]);
d
->
requestedSize
=
d
->
hwCapableSize
;
}
else
if
(
hwSize
>
rqSize
)
{
d
->
requestedSize
.
width
,
d
->
requestedSize
.
height
,
(
int
)
(
res
[
0
]
*
downscale
),
(
int
)
(
res
[
1
]
*
downscale
));
d
->
requestedSize
.
width
=
(
int
)
(
d
->
hwCapableSize
.
width
*
downscale
);
d
->
requestedSize
.
height
=
(
int
)
(
d
->
hwCapableSize
.
height
*
downscale
);
}
else
if
((
hwSize
*
downscale
*
downscale
)
>
rqSize
)
{
ms_message
(
"Camera cannot produce requested resolution %dx%d, will capture a bigger one (%dx%d) and crop it to match encoder requested resolution
\n
"
,
d
->
requestedSize
.
width
,
d
->
requestedSize
.
height
,
res
[
0
],
res
[
1
]
);
d
->
requestedSize
.
width
,
d
->
requestedSize
.
height
,
(
int
)(
res
[
0
]
*
downscale
),
(
int
)(
res
[
1
]
*
downscale
)
);
}
// is phone held |_ to cam orientation ?
if
(
d
->
rotation
==
UNDEFINED_ROTATION
||
compute_image_rotation_correction
(
d
,
d
->
rotation
)
%
180
!=
0
)
{
if
(
d
->
rotation
==
UNDEFINED_ROTATION
)
{
...
...
@@ -476,14 +481,15 @@ JNIEXPORT void JNICALL Java_org_linphone_mediastream_video_capture_AndroidVideoA
It only implies one thing: image needs to rotated by that amount to be correctly
displayed.
*/
mblk_t
*
yuv_block
=
copy_ycbcrbiplanar_to_true_yuv_with_rotation
(
y_src
mblk_t
*
yuv_block
=
copy_ycbcrbiplanar_to_true_yuv_with_rotation
_and_down_scale_by_2
(
y_src
,
cbcr_src
,
image_rotation_correction
,
d
->
requestedSize
.
width
,
d
->
requestedSize
.
height
,
d
->
hwCapableSize
.
width
,
d
->
hwCapableSize
.
width
,
false
);
false
,
d
->
useDownscaling
);
if
(
yuv_block
)
{
if
(
d
->
frame
)
freemsg
(
d
->
frame
);
...
...
src/msvideo.c
View file @
2841874a
...
...
@@ -395,10 +395,14 @@ static MSScalerContext *ff_create_swscale_context(int src_w, int src_h, MSPixFmt
int
ff_flags
=
0
;
MSFFScalerContext
*
ctx
=
ms_new
(
MSFFScalerContext
,
1
);
ctx
->
src_h
=
src_h
;
#if (TARGET_OS_IPHONE)
ff_flags
|=
SWS_FAST_BILINEAR
;
#else
if
(
flags
&
MS_SCALER_METHOD_BILINEAR
)
ff_flags
|=
SWS_BILINEAR
;
else
if
(
flags
&
MS_SCALER_METHOD_NEIGHBOUR
)
ff_flags
|=
SWS_BILINEAR
;
#endif
ctx
->
ctx
=
sws_getContext
(
src_w
,
src_h
,
ms_pix_fmt_to_ffmpeg
(
src_fmt
),
dst_w
,
dst_h
,
ms_pix_fmt_to_ffmpeg
(
dst_fmt
),
ff_flags
,
NULL
,
NULL
,
NULL
);
if
(
ctx
->
ctx
==
NULL
){
...
...
@@ -557,7 +561,6 @@ static void rotate_plane(int wDest, int hDest, int full_width, uint8_t* src, uin
int
signed_dst_stride
;
int
incr
;
int
y
,
x
;
...
...
@@ -572,6 +575,7 @@ static void rotate_plane(int wDest, int hDest, int full_width, uint8_t* src, uin
incr
=
-
1
;
signed_dst_stride
=
-
wDest
;
}
int
y
,
x
;
for
(
y
=
0
;
y
<
hSrc
;
y
++
)
{
uint8_t
*
dst2
=
dst
;
for
(
x
=
0
;
x
<
step
*
wSrc
;
x
+=
step
)
{
...
...
@@ -593,22 +597,23 @@ static void rotate_plane(int wDest, int hDest, int full_width, uint8_t* src, uin
static
int
hasNeon
=
-
1
;
#elif defined (__ARM_NEON__)
static
int
hasNeon
=
1
;
#el
if defined (__arm__)
#el
se
static
int
hasNeon
=
0
;
#endif
/* Destination and source images may have their dimensions inverted.*/
mblk_t
*
copy_ycbcrbiplanar_to_true_yuv_with_rotation
(
uint8_t
*
y
,
uint8_t
*
cbcr
,
int
rotation
,
int
w
,
int
h
,
int
y_byte_per_row
,
int
cbcr_byte_per_row
,
bool_t
uFirstvSecond
)
{
mblk_t
*
copy_ycbcrbiplanar_to_true_yuv_with_rotation
_and_down_scale_by_2
(
uint8_t
*
y
,
uint8_t
*
cbcr
,
int
rotation
,
int
w
,
int
h
,
int
y_byte_per_row
,
int
cbcr_byte_per_row
,
bool_t
uFirstvSecond
,
bool_t
down_scale
)
{
MSPicture
pict
;
mblk_t
*
yuv_block
=
ms_yuv_buf_alloc
(
&
pict
,
w
,
h
);
int
uv_w
=
w
/
2
;
int
uv_h
=
h
/
2
;
#ifdef ANDROID
if
(
hasNeon
==
-
1
)
{
hasNeon
=
(
android_getCpuFamily
()
==
ANDROID_CPU_FAMILY_ARM
&&
(
android_getCpuFeatures
()
&
ANDROID_CPU_ARM_FEATURE_NEON
)
!=
0
);
}
#endif
if
(
down_scale
&&
!
hasNeon
)
{
ms_error
(
"down scaling by two requires NEON, returning empty block"
);
return
yuv_block
;
}
if
(
!
uFirstvSecond
)
{
unsigned
char
*
tmp
=
pict
.
planes
[
1
];
...
...
@@ -616,38 +621,47 @@ mblk_t *copy_ycbcrbiplanar_to_true_yuv_with_rotation(uint8_t* y, uint8_t * cbcr,
pict
.
planes
[
2
]
=
tmp
;
}
int
uv_w
=
w
/
2
;
int
uv_h
=
h
/
2
;
if
(
rotation
%
180
==
0
)
{
int
i
,
j
;
uint8_t
*
u_dest
=
pict
.
planes
[
1
],
*
v_dest
=
pict
.
planes
[
2
];
if
(
rotation
==
0
)
{
// plain copy
for
(
i
=
0
;
i
<
h
;
i
++
)
{
memcpy
(
&
pict
.
planes
[
0
][
i
*
w
],
&
y
[
i
*
y_byte_per_row
],
w
);
}
// de-interlace u/v
for
(
i
=
0
;
i
<
uv_h
;
i
++
)
{
for
(
j
=
0
;
j
<
uv_w
;
j
++
)
{
*
u_dest
++
=
cbcr
[
cbcr_byte_per_row
*
i
+
2
*
j
];
*
v_dest
++
=
cbcr
[
cbcr_byte_per_row
*
i
+
2
*
j
+
1
];
#ifdef __arm__
if
(
hasNeon
)
{
deinterlace_down_scale_neon
(
y
,
cbcr
,
pict
.
planes
[
0
],
u_dest
,
v_dest
,
w
,
h
,
y_byte_per_row
,
cbcr_byte_per_row
,
down_scale
);
}
else
#endif
{
// plain copy
for
(
i
=
0
;
i
<
h
;
i
++
)
{
memcpy
(
&
pict
.
planes
[
0
][
i
*
w
],
&
y
[
i
*
y_byte_per_row
],
w
);
}
// de-interlace u/v
for
(
i
=
0
;
i
<
uv_h
;
i
++
)
{
for
(
j
=
0
;
j
<
uv_w
;
j
++
)
{
*
u_dest
++
=
cbcr
[
cbcr_byte_per_row
*
i
+
2
*
j
];
*
v_dest
++
=
cbcr
[
cbcr_byte_per_row
*
i
+
2
*
j
+
1
];
}
}
}
}
else
{
#ifdef __arm__
if
(
hasNeon
)
{
deinterlace_
and_rotate_180_neon
(
y
,
cbcr
,
pict
.
planes
[
0
],
u_dest
,
v_dest
,
w
,
h
,
y_byte_per_row
,
cbcr_byte_per_row
);
deinterlace_
down_scale_and_rotate_180_neon
(
y
,
cbcr
,
pict
.
planes
[
0
],
u_dest
,
v_dest
,
w
,
h
,
y_byte_per_row
,
cbcr_byte_per_row
,
down_scale
);
}
else
#endif
{
// 180° y rotation
uint8_t
*
ysrc
=
y
;
uint8_t
*
uvsrc
=&
cbcr
[
uv_h
*
uv_w
*
2
-
2
];
uint8_t
*
ydst
=&
pict
.
planes
[
0
][
h
*
w
-
1
];
// 180° y rotation
for
(
i
=
0
;
i
<
h
*
w
;
i
++
)
{
*
ydst
--
=
*
ysrc
++
;
}
// 180° rotation + de-interlace u/v
uint8_t
*
uvsrc
=&
cbcr
[
uv_h
*
uv_w
*
2
-
2
];
for
(
i
=
0
;
i
<
uv_h
*
uv_w
*
2
;
i
++
)
{
*
u_dest
++
=
*
uvsrc
--
;
*
v_dest
++
=
*
uvsrc
--
;
...
...
@@ -660,7 +674,7 @@ mblk_t *copy_ycbcrbiplanar_to_true_yuv_with_rotation(uint8_t* y, uint8_t * cbcr,
#ifdef __arm__
if
(
hasNeon
)
{
if
(
clockwise
)
{
rotate_
plane_neon_clockwise
(
w
,
h
,
y_byte_per_row
,(
uint8_t
*
)
y
,
pict
.
planes
[
0
]
);
rotate_
down_scale_plane_neon_clockwise
(
w
,
h
,
y_byte_per_row
,(
uint8_t
*
)
y
,
pict
.
planes
[
0
],
down_scale
);
}
else
{
rotate_plane_neon_anticlockwise
(
w
,
h
,
y_byte_per_row
,(
uint8_t
*
)
y
,
pict
.
planes
[
0
]);
}
...
...
@@ -674,25 +688,26 @@ mblk_t *copy_ycbcrbiplanar_to_true_yuv_with_rotation(uint8_t* y, uint8_t * cbcr,
#ifdef __arm__
if
(
hasNeon
)
{
rotate_
cbcr_to_cr_cb
(
uv_w
,
uv_h
,
cbcr_byte_per_row
/
2
,
(
uint8_t
*
)
cbcr
,
pict
.
planes
[
2
],
pict
.
planes
[
1
],
clockwis
e
);
rotate_
down_scale_cbcr_to_cr_cb
(
uv_w
,
uv_h
,
cbcr_byte_per_row
/
2
,
(
uint8_t
*
)
cbcr
,
pict
.
planes
[
2
],
pict
.
planes
[
1
],
clockwise
,
down_scal
e
);
}
else
#endif
{
// Copying U
uint8_t
*
srcu
=
cbcr
;
uint8_t
*
dstu
=
pict
.
planes
[
1
];
uint8_t
*
srcv
=
srcu
+
1
;
uint8_t
*
dstv
=
pict
.
planes
[
2
];
// Copying U
rotate_plane
(
uv_w
,
uv_h
,
cbcr_byte_per_row
/
2
,
srcu
,
dstu
,
2
,
clockwise
);
// Copying V
uint8_t
*
srcv
=
srcu
+
1
;
uint8_t
*
dstv
=
pict
.
planes
[
2
];
rotate_plane
(
uv_w
,
uv_h
,
cbcr_byte_per_row
/
2
,
srcv
,
dstv
,
2
,
clockwise
);
}
}
return
yuv_block
;
}
mblk_t
*
copy_ycbcrbiplanar_to_true_yuv_with_rotation
(
uint8_t
*
y
,
uint8_t
*
cbcr
,
int
rotation
,
int
w
,
int
h
,
int
y_byte_per_row
,
int
cbcr_byte_per_row
,
bool_t
uFirstvSecond
)
{
return
copy_ycbcrbiplanar_to_true_yuv_with_rotation_and_down_scale_by_2
(
y
,
cbcr
,
rotation
,
w
,
h
,
y_byte_per_row
,
cbcr_byte_per_row
,
uFirstvSecond
,
FALSE
);
}
void
ms_video_init_framerate_controller
(
MSFrameRateController
*
ctrl
,
float
fps
)
{
ctrl
->
start_time
=
0
;
ctrl
->
th_frame_count
=
-
1
;
...
...
src/msvideo_neon.c
View file @
2841874a
This diff is collapsed.
Click to expand it.
src/videostream.c
View file @
2841874a
...
...
@@ -27,7 +27,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/msrtp.h"
#include "mediastreamer2/msvideoout.h"
#include "mediastreamer2/msextdisplay.h"
#ifndef TARGET_OS_IPHONE
#include <ortp/zrtp.h>
#endif
#ifndef TARGET_OS_IPHONE
#define TARGET_OS_IPHONE 0
...
...
@@ -206,6 +208,8 @@ static void choose_display_name(VideoStream *stream){
stream
->
display_name
=
ms_strdup
(
"MSAndroidDisplay"
);
#elif defined (HAVE_X11_EXTENSIONS_XV_H)
stream
->
display_name
=
ms_strdup
(
"MSX11Video"
);
#elif defined (TARGET_OS_IPHONE)
stream
->
display_name
=
ms_strdup
(
"IOSDisplay"
);
#else
stream
->
display_name
=
ms_strdup
(
"MSVideoOut"
);
#endif
...
...
@@ -236,10 +240,10 @@ void video_stream_set_relay_session_id(VideoStream *stream, const char *id){
void
video_stream_enable_self_view
(
VideoStream
*
stream
,
bool_t
val
){
MSFilter
*
out
=
stream
->
output
;
stream
->
corner
=
val
?
0
:
-
1
;
if
(
out
)
{
ms_filter_call_method
(
out
,
MS_VIDEO_DISPLAY_SET_LOCAL_VIEW_MODE
,
&
stream
->
corner
);
}
stream
->
corner
=
val
?
0
:
-
1
;
if
(
out
)
{
ms_filter_call_method
(
out
,
MS_VIDEO_DISPLAY_SET_LOCAL_VIEW_MODE
,
&
stream
->
corner
);
}
}
void
video_stream_enable_adaptive_bitrate_control
(
VideoStream
*
s
,
bool_t
yesno
){
...
...
@@ -284,7 +288,7 @@ static MSVideoSize get_compatible_size(MSVideoSize maxsize, MSVideoSize wished_s
int
max_area
=
maxsize
.
width
*
maxsize
.
height
;
int
whished_area
=
wished_size
.
width
*
wished_size
.
height
;
if
(
whished_area
>
max_area
){
return
m
s_video_size_change_orientation
(
maxsize
,
ms_video_size_get_orientation
(
wished_size
))
;
return
m
axsize
;
}
return
wished_size
;
}
...
...
@@ -359,9 +363,6 @@ int video_stream_start (VideoStream *stream, RtpProfile *profile, const char *re
rtp_session_set_profile
(
rtps
,
profile
);
if
(
remport
>
0
)
rtp_session_set_remote_addr_full
(
rtps
,
remip
,
remport
,
rem_rtcp_port
);
if
(
rem_rtcp_port
<=
0
){
rtp_session_enable_rtcp
(
rtps
,
FALSE
);
}
rtp_session_set_payload_type
(
rtps
,
payload
);
rtp_session_set_jitter_compensation
(
rtps
,
jitt_comp
);
...
...
@@ -498,7 +499,7 @@ void video_stream_update_video_params(VideoStream *stream){
void
video_stream_change_camera
(
VideoStream
*
stream
,
MSWebCam
*
cam
){
bool_t
keep_source
=
(
cam
==
stream
->
cam
);
if
(
stream
->
ticker
&&
stream
->
source
){
ms_ticker_detach
(
stream
->
ticker
,
stream
->
source
);
/*unlink source filters and subsequent post processin filters */
...
...
@@ -514,7 +515,7 @@ void video_stream_change_camera(VideoStream *stream, MSWebCam *cam){
if
(
!
keep_source
)
stream
->
source
=
ms_web_cam_create_reader
(
cam
);
stream
->
cam
=
cam
;
configure_video_source
(
stream
);
ms_filter_link
(
stream
->
source
,
0
,
stream
->
pixconv
,
0
);
ms_filter_link
(
stream
->
pixconv
,
0
,
stream
->
sizeconv
,
0
);
ms_filter_link
(
stream
->
sizeconv
,
0
,
stream
->
tee
,
0
);
...
...
@@ -609,7 +610,7 @@ unsigned long video_stream_get_native_preview_window_id(VideoStream *stream){
return
id
;
}
if
(
stream
->
source
){
if
(
ms_filter_has_method
(
stream
->
source
,
MS_VIDEO_DISPLAY_GET_NATIVE_WINDOW_ID
)
if
(
ms_filter_has_method
(
stream
->
source
,
MS_VIDEO_DISPLAY_GET_NATIVE_WINDOW_ID
)
&&
ms_filter_call_method
(
stream
->
source
,
MS_VIDEO_DISPLAY_GET_NATIVE_WINDOW_ID
,
&
id
)
==
0
)
return
id
;
}
...
...
@@ -621,12 +622,11 @@ void video_stream_use_preview_video_window(VideoStream *stream, bool_t yesno){
}
void
video_stream_set_device_rotation
(
VideoStream
*
stream
,
int
orientation
){
MSFilter
*
target_filter
=
NULL
;
if
(
stream
==
0
)
return
;
stream
->
device_orientation
=
orientation
;
target_filter
=
stream
->
source
;
MSFilter
*
target_filter
=
stream
->
source
;
if
(
target_filter
){
ms_filter_call_method
(
target_filter
,
MS_VIDEO_CAPTURE_SET_DEVICE_ORIENTATION
,
&
orientation
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment