android: robustifying Android Video Capture filter

parent ff7733bf
......@@ -57,7 +57,7 @@ struct AndroidReaderContext {
ms_mutex_init(&mutex,NULL);
androidCamera = 0;
previewWindow = 0;
rotation = UNDEFINED_ROTATION;
rotation = rotationSavedDuringVSize = UNDEFINED_ROTATION;
};
~AndroidReaderContext(){
......@@ -77,7 +77,7 @@ struct AndroidReaderContext {
float fps;
MSVideoSize requestedSize, hwCapableSize;
ms_mutex_t mutex;
int rotation;
int rotation, rotationSavedDuringVSize;
jobject androidCamera;
jobject previewWindow;
......@@ -85,7 +85,7 @@ struct AndroidReaderContext {
/************************ Private helper methods ************************/
static jclass getHelperClass(JNIEnv *env);
static int compute_image_rotation_correction(AndroidReaderContext* d);
static int compute_image_rotation_correction(AndroidReaderContext* d, int rotation);
static void compute_cropping_offsets(MSVideoSize hwSize, MSVideoSize outputSize, int* yoff, int* cbcroff);
static AndroidReaderContext *getContext(MSFilter *f);
......@@ -124,7 +124,7 @@ static int video_capture_set_vsize(MSFilter *f, void* data){
// handle result :
// - 0 : width
// - 1 : height
// - 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);
......@@ -145,9 +145,15 @@ static int video_capture_set_vsize(MSFilter *f, void* data){
}
// is phone held |_ to cam orientation ?
if (d->rotation == UNDEFINED_ROTATION || compute_image_rotation_correction(d) % 180 != 0) {
if (d->rotation == UNDEFINED_ROTATION)
ms_warning("Capture filter do not know yet about device's orientation.\nCurrent assumption: device is held perpendicular to its webcam (ie: portrait mode for a phone)\n");
if (d->rotation == UNDEFINED_ROTATION || compute_image_rotation_correction(d, d->rotation) % 180 != 0) {
if (d->rotation == UNDEFINED_ROTATION) {
ms_error("To produce a correct image, Mediastreamer MUST be aware of device's orientation BEFORE calling 'configure_video_source'\n");
ms_warning("Capture filter do not know yet about device's orientation.\n"
"Current assumption: device is held perpendicular to its webcam (ie: portrait mode for a phone)\n");
d->rotationSavedDuringVSize = 0;
} else {
d->rotationSavedDuringVSize = d->rotation;
}
bool camIsLandscape = d->hwCapableSize.width > d->hwCapableSize.height;
bool reqIsLandscape = d->requestedSize.width > d->requestedSize.height;
......@@ -158,7 +164,10 @@ static int video_capture_set_vsize(MSFilter *f, void* data){
d->requestedSize.height = t;
ms_message("Swapped resolution width and height to : %dx%d\n", d->requestedSize.width, d->requestedSize.height);
}
} else {
d->rotationSavedDuringVSize = d->rotation;
}
ms_mutex_unlock(&d->mutex);
return 0;
}
......@@ -194,30 +203,30 @@ static int video_set_native_preview_window(MSFilter *f, void *arg) {
if (d->androidCamera) {
if (d->previewWindow == 0) {
ms_message("Preview capture window set for the 1st time (rotation:%d)\n", d->rotation);
// env->CallStaticVoidMethod(helperClass, method, d->androidCamera, w);
} else {
ms_message("Preview capture window changed (rotation:%d)\n", d->rotation);
env->DeleteGlobalRef(d->androidCamera);
if (w) {
env->CallStaticVoidMethod(helperClass,
env->GetStaticMethodID(helperClass,"stopRecording", "(Ljava/lang/Object;)V"),
d->androidCamera);
d->androidCamera = env->NewGlobalRef(
env->CallStaticObjectMethod(helperClass,
env->GetStaticMethodID(helperClass,"startRecording", "(IIIIIJ)Ljava/lang/Object;"),
((AndroidWebcamConfig*)d->webcam->data)->id,
d->hwCapableSize.width,
d->hwCapableSize.height,
(jint)d->fps,
(d->rotation != UNDEFINED_ROTATION) ? d->rotation:0,
(jlong)d));
}
}
if (w) {
env->CallStaticVoidMethod(helperClass,
env->GetStaticMethodID(helperClass,"stopRecording", "(Ljava/lang/Object;)V"),
d->androidCamera);
d->androidCamera = env->NewGlobalRef(
env->CallStaticObjectMethod(helperClass,
env->GetStaticMethodID(helperClass,"startRecording", "(IIIIIJ)Ljava/lang/Object;"),
((AndroidWebcamConfig*)d->webcam->data)->id,
d->hwCapableSize.width,
d->hwCapableSize.height,
(jint)d->fps,
(d->rotation != UNDEFINED_ROTATION) ? d->rotation:0,
(jlong)d));
// if previewWindow AND camera are valid => set preview window
if (w && d->androidCamera)
env->CallStaticVoidMethod(helperClass, method, d->androidCamera, w);
}
} else {
ms_message("Preview capture window set but camera not created yet; remembering it for later use\n");
}
......@@ -236,7 +245,7 @@ static int video_get_native_preview_window(MSFilter *f, void *arg) {
static int video_set_device_rotation(MSFilter* f, void* arg) {
AndroidReaderContext* d = (AndroidReaderContext*) f->data;
d->rotation=*((int*)arg);
ms_message("%s : %d\n", __FUNCTION__, d->rotation);
ms_message("%s : %d\n", __FUNCTION__, d->rotation);
return 0;
}
......@@ -260,7 +269,7 @@ void video_capture_preprocess(MSFilter *f){
d->hwCapableSize.width,
d->hwCapableSize.height,
(jint)d->fps,
(d->rotation != UNDEFINED_ROTATION) ? d->rotation:0,
d->rotationSavedDuringVSize,
(jlong)d);
d->androidCamera = env->NewGlobalRef(cam);
......@@ -427,13 +436,13 @@ JNIEXPORT void JNICALL Java_org_linphone_mediastream_video_capture_AndroidVideoA
return;
}
if (d->rotation == UNDEFINED_ROTATION) {
ms_mutex_unlock(&d->mutex);
ms_warning("Cannot produce image: we do not know yet about device's orientation. Dropping camera frame\n");
return;
if (d->rotation != UNDEFINED_ROTATION && d->rotationSavedDuringVSize != d->rotation) {
ms_warning("Rotation has changed (new value: %d) since vsize was run (old value: %d)."
"Will produce inverted images. Use set_device_orientation() then update call.\n",
d->rotation, d->rotationSavedDuringVSize);
}
int image_rotation_correction = (d->rotation != UNDEFINED_ROTATION) ? compute_image_rotation_correction(d) : 0;
int image_rotation_correction = compute_image_rotation_correction(d, d->rotationSavedDuringVSize);
jboolean isCopied;
jbyte* jinternal_buff = env->GetByteArrayElements(frame, &isCopied);
......@@ -455,7 +464,6 @@ 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.
*/
#if 1
mblk_t* yuv_block = copy_ycbcrbiplanar_to_true_yuv_with_rotation(y_src
, cbcr_src
, image_rotation_correction
......@@ -464,12 +472,6 @@ JNIEXPORT void JNICALL Java_org_linphone_mediastream_video_capture_AndroidVideoA
, d->hwCapableSize.width
, d->hwCapableSize.width,
false);
#else
MSPicture pict;
mblk_t *yuv_block = ms_yuv_buf_alloc(&pict, d->requestedSize.width, d->requestedSize.height);
for(int i=0; i<pict.w * pict.h; i++)
pict.planes[0][i]=128;
#endif
if (yuv_block) {
if (d->frame)
freemsg(d->frame);
......@@ -485,16 +487,16 @@ for(int i=0; i<pict.w * pict.h; i++)
}
#endif
static int compute_image_rotation_correction(AndroidReaderContext* d) {
static int compute_image_rotation_correction(AndroidReaderContext* d, int rotation) {
AndroidWebcamConfig* conf = (AndroidWebcamConfig*)(AndroidWebcamConfig*)d->webcam->data;
int result;
if (conf->frontFacing) {
ms_debug("%s: %d + %d\n", __FUNCTION__, ((AndroidWebcamConfig*)d->webcam->data)->orientation, d->rotation);
result = ((AndroidWebcamConfig*)d->webcam->data)->orientation + d->rotation;
ms_debug("%s: %d + %d\n", __FUNCTION__, ((AndroidWebcamConfig*)d->webcam->data)->orientation, rotation);
result = ((AndroidWebcamConfig*)d->webcam->data)->orientation + rotation;
} else {
ms_debug("%s: %d - %d\n", __FUNCTION__, ((AndroidWebcamConfig*)d->webcam->data)->orientation, d->rotation);
result = ((AndroidWebcamConfig*)d->webcam->data)->orientation - d->rotation;
ms_debug("%s: %d - %d\n", __FUNCTION__, ((AndroidWebcamConfig*)d->webcam->data)->orientation, rotation);
result = ((AndroidWebcamConfig*)d->webcam->data)->orientation - rotation;
}
while(result < 0)
result += 360;
......@@ -502,7 +504,7 @@ static int compute_image_rotation_correction(AndroidReaderContext* d) {
}
static void compute_cropping_offsets(MSVideoSize hwSize, MSVideoSize outputSize, int* yoff, int* cbcroff) {
// if hw <= out => return
// if hw <= out -> return
if (hwSize.width * hwSize.height <= outputSize.width * outputSize.height) {
*yoff = 0;
*cbcroff = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment