Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
35cb59bb
Commit
35cb59bb
authored
Aug 16, 2013
by
Roman Donchenko
Committed by
OpenCV Buildbot
Aug 16, 2013
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1258 from apavlenko:java_video_capture
parents
95143fdc
5a9bd3f0
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
261 additions
and
258 deletions
+261
-258
gen_java.py
modules/java/generator/gen_java.py
+87
-17
VideoCapture.cpp
modules/java/generator/src/cpp/VideoCapture.cpp
+0
-0
videocap_compat.cpp
modules/java/generator/src/cpp/videocap_compat.cpp
+173
-0
highgui+VideoCapture.java
modules/java/generator/src/java/highgui+VideoCapture.java
+0
-240
OpenCVTestCase.java
modules/java/test/src/org/opencv/test/OpenCVTestCase.java
+1
-1
No files found.
modules/java/generator/gen_java.py
View file @
35cb59bb
...
...
@@ -12,7 +12,7 @@ class_ignore_list = (
#core
"FileNode"
,
"FileStorage"
,
"KDTree"
,
#highgui
"VideoWriter"
,
"VideoCapture"
,
"VideoWriter"
,
)
const_ignore_list
=
(
...
...
@@ -512,6 +512,54 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1getTextSize
"resizeWindow"
:
{
'j_code'
:
''
,
'jn_code'
:
''
,
'cpp_code'
:
''
},
},
# Highgui
'VideoCapture'
:
{
"getSupportedPreviewSizes"
:
{
'j_code'
:
"""
public java.util.List<org.opencv.core.Size> getSupportedPreviewSizes()
{
String[] sizes_str = getSupportedPreviewSizes_0(nativeObj).split(",");
java.util.List<org.opencv.core.Size> sizes = new java.util.ArrayList<org.opencv.core.Size>(sizes_str.length);
for (String str : sizes_str) {
String[] wh = str.split("x");
sizes.add(new org.opencv.core.Size(Double.parseDouble(wh[0]), Double.parseDouble(wh[1])));
}
return sizes;
}
"""
,
'jn_code'
:
"""
\n
private static native String getSupportedPreviewSizes_0(long nativeObj);
\n
"""
,
'cpp_code'
:
"""
JNIEXPORT jstring JNICALL Java_org_opencv_highgui_VideoCapture_getSupportedPreviewSizes_10
(JNIEnv *env, jclass, jlong self);
JNIEXPORT jstring JNICALL Java_org_opencv_highgui_VideoCapture_getSupportedPreviewSizes_10
(JNIEnv *env, jclass, jlong self)
{
static const char method_name[] = "highgui::VideoCapture_getSupportedPreviewSizes_10()";
try {
LOGD(
%
s, method_name);
VideoCapture* me = (VideoCapture*) self; //TODO: check for NULL
union {double prop; const char* name;} u;
u.prop = me->get(CV_CAP_PROP_SUPPORTED_PREVIEW_SIZES_STRING);
return env->NewStringUTF(u.name);
} catch(const std::exception &e) {
throwJavaException(env, &e, method_name);
} catch (...) {
throwJavaException(env, 0, method_name);
}
return env->NewStringUTF("");
}
"""
,
},
# getSupportedPreviewSizes
},
# VideoCapture
}
# { class : { func : {arg_name : ctype} } }
...
...
@@ -878,21 +926,48 @@ public class %(jc)s {
self
.
add_func
(
decl
)
self
.
cpp_code
=
StringIO
()
self
.
cpp_code
.
write
(
"""
self
.
cpp_code
.
write
(
Template
(
"""
//
// This file is auto-generated, please don't edit!
//
#define LOG_TAG "org.opencv.
%(m)
s
"
#define LOG_TAG "org.opencv.
$m
"
#include "common.h"
#include "opencv2/
%(m)
s/
%(m)
s.hpp"
#include "opencv2/opencv_modules.hpp"
#ifdef HAVE_OPENCV_$M
#include "opencv2/$m/$m.hpp"
using namespace cv;
/// throw java exception
static void throwJavaException(JNIEnv *env, const std::exception *e, const char *method) {
std::string what = "unknown exception";
jclass je = 0;
if(e) {
std::string exception_type = "std::exception";
if(dynamic_cast<const cv::Exception*>(e)) {
exception_type = "cv::Exception";
je = env->FindClass("org/opencv/core/CvException");
}
what = exception_type + ": " + e->what();
}
if(!je) je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, what.c_str());
LOGE("
%
s caught
%
s", method, what.c_str());
(void)method; // avoid "unused" warning
}
extern "C" {
"""
%
{
'm'
:
module
}
)
"""
)
.
substitute
(
m
=
module
,
M
=
module
.
upper
()
)
)
# generate code for the classes
for
name
in
self
.
classes
.
keys
():
...
...
@@ -907,7 +982,7 @@ extern "C" {
java_code
=
Template
(
java_code
)
.
substitute
(
imports
=
imports
)
self
.
save
(
"
%
s/
%
s+
%
s.java"
%
(
output_path
,
module
,
self
.
classes
[
name
]
.
jname
),
java_code
)
self
.
cpp_code
.
write
(
'
\n
} // extern "C"
\n
'
)
self
.
cpp_code
.
write
(
'
\n
} // extern "C"
\n
\n
#endif // HAVE_OPENCV_
%
s
\n
'
%
module
.
upper
()
)
self
.
save
(
output_path
+
"/"
+
module
+
".cpp"
,
self
.
cpp_code
.
getvalue
())
# report
...
...
@@ -1266,23 +1341,18 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname ($argst);
JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname
($args)
{
static const char method_name[] = "$module::$fname()";
try {
LOGD("
$module::$fname()"
);
LOGD("
%
s", method_name
);
$prologue
$retval$cvname( $cvargs );
$epilogue$ret
} catch(cv::Exception e) {
LOGD("$module::$fname() catched cv::Exception:
%
s", e.what());
jclass je = env->FindClass("org/opencv/core/CvException");
if(!je) je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, e.what());
$default
} catch(const std::exception &e) {
throwJavaException(env, &e, method_name);
} catch (...) {
LOGD("$module::$fname() catched unknown exception (...)");
jclass je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, "Unknown exception in JNI code {$module::$fname()}");
$default
throwJavaException(env, 0, method_name);
}
$default
}
...
...
modules/java/generator/src/cpp/VideoCapture.cpp
deleted
100644 → 0
View file @
95143fdc
This diff is collapsed.
Click to expand it.
modules/java/generator/src/cpp/videocap_compat.cpp
0 → 100644
View file @
35cb59bb
// emulating the 'old' JNI names existed before the VideoCapture wrapping became automatic
#define LOG_TAG "org.opencv.highgui.VideoCapture"
#include "common.h"
#include "opencv2/opencv_modules.hpp"
#ifdef HAVE_OPENCV_HIGHGUI
#include "opencv2/core/version.hpp"
#if (CV_VERSION_EPOCH == 2) && (CV_VERSION_MAJOR == 4)
extern
"C"
{
JNIEXPORT
jlong
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1VideoCapture__
(
JNIEnv
*
env
,
jclass
c
);
JNIEXPORT
jlong
JNICALL
Java_org_opencv_highgui_VideoCapture_VideoCapture_10
(
JNIEnv
*
,
jclass
);
JNIEXPORT
jlong
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1VideoCapture__
(
JNIEnv
*
env
,
jclass
c
)
{
return
Java_org_opencv_highgui_VideoCapture_VideoCapture_10
(
env
,
c
);
}
JNIEXPORT
jlong
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1VideoCapture__I
(
JNIEnv
*
env
,
jclass
c
,
jint
device
);
JNIEXPORT
jlong
JNICALL
Java_org_opencv_highgui_VideoCapture_VideoCapture_12
(
JNIEnv
*
,
jclass
,
jint
);
JNIEXPORT
jlong
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1VideoCapture__I
(
JNIEnv
*
env
,
jclass
c
,
jint
device
)
{
return
Java_org_opencv_highgui_VideoCapture_VideoCapture_12
(
env
,
c
,
device
);
}
JNIEXPORT
jdouble
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1get
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
,
jint
propId
);
JNIEXPORT
jdouble
JNICALL
Java_org_opencv_highgui_VideoCapture_get_10
(
JNIEnv
*
,
jclass
,
jlong
,
jint
);
JNIEXPORT
jdouble
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1get
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
,
jint
propId
)
{
return
Java_org_opencv_highgui_VideoCapture_get_10
(
env
,
c
,
self
,
propId
);
}
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1grab
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_grab_10
(
JNIEnv
*
,
jclass
,
jlong
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1grab
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
)
{
return
Java_org_opencv_highgui_VideoCapture_grab_10
(
env
,
c
,
self
);
}
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1isOpened
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_isOpened_10
(
JNIEnv
*
,
jclass
,
jlong
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1isOpened
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
)
{
return
Java_org_opencv_highgui_VideoCapture_isOpened_10
(
env
,
c
,
self
);
}
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1open__JI
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
,
jint
device
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_open_11
(
JNIEnv
*
,
jclass
,
jlong
,
jint
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1open__JI
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
,
jint
device
)
{
return
Java_org_opencv_highgui_VideoCapture_open_11
(
env
,
c
,
self
,
device
);
}
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1read
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
,
jlong
image_nativeObj
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_read_10
(
JNIEnv
*
,
jclass
,
jlong
,
jlong
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1read
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
,
jlong
image_nativeObj
)
{
return
Java_org_opencv_highgui_VideoCapture_read_10
(
env
,
c
,
self
,
image_nativeObj
);
}
JNIEXPORT
void
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1release
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
);
JNIEXPORT
void
JNICALL
Java_org_opencv_highgui_VideoCapture_release_10
(
JNIEnv
*
,
jclass
,
jlong
);
JNIEXPORT
void
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1release
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
)
{
Java_org_opencv_highgui_VideoCapture_release_10
(
env
,
c
,
self
);
}
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1retrieve__JJI
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
,
jlong
image_nativeObj
,
jint
channel
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_retrieve_10
(
JNIEnv
*
,
jclass
,
jlong
,
jlong
,
jint
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1retrieve__JJI
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
,
jlong
image_nativeObj
,
jint
channel
)
{
return
Java_org_opencv_highgui_VideoCapture_retrieve_10
(
env
,
c
,
self
,
image_nativeObj
,
channel
);
}
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1retrieve__JJ
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
,
jlong
image_nativeObj
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_retrieve_11
(
JNIEnv
*
,
jclass
,
jlong
,
jlong
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1retrieve__JJ
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
,
jlong
image_nativeObj
)
{
return
Java_org_opencv_highgui_VideoCapture_retrieve_11
(
env
,
c
,
self
,
image_nativeObj
);
}
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1set
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
,
jint
propId
,
jdouble
value
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_set_10
(
JNIEnv
*
,
jclass
,
jlong
,
jint
,
jdouble
);
JNIEXPORT
jboolean
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1set
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
,
jint
propId
,
jdouble
value
)
{
return
Java_org_opencv_highgui_VideoCapture_set_10
(
env
,
c
,
self
,
propId
,
value
);
}
JNIEXPORT
jstring
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1getSupportedPreviewSizes
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
);
JNIEXPORT
jstring
JNICALL
Java_org_opencv_highgui_VideoCapture_getSupportedPreviewSizes_10
(
JNIEnv
*
env
,
jclass
,
jlong
self
);
JNIEXPORT
jstring
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1getSupportedPreviewSizes
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
)
{
return
Java_org_opencv_highgui_VideoCapture_getSupportedPreviewSizes_10
(
env
,
c
,
self
);
}
JNIEXPORT
void
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1delete
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
);
JNIEXPORT
void
JNICALL
Java_org_opencv_highgui_VideoCapture_delete
(
JNIEnv
*
,
jclass
,
jlong
);
JNIEXPORT
void
JNICALL
Java_org_opencv_highgui_VideoCapture_n_1delete
(
JNIEnv
*
env
,
jclass
c
,
jlong
self
)
{
Java_org_opencv_highgui_VideoCapture_delete
(
env
,
c
,
self
);
}
}
// extern "C"
#endif // (CV_VERSION_EPOCH == 2) && (CV_VERSION_MAJOR == 4)
#endif // HAVE_OPENCV_HIGHGUI
modules/java/generator/src/java/highgui+VideoCapture.java
deleted
100644 → 0
View file @
95143fdc
package
org
.
opencv
.
highgui
;
import
java.util.List
;
import
java.util.LinkedList
;
import
org.opencv.core.Mat
;
import
org.opencv.core.Size
;
// C++: class VideoCapture
//javadoc: VideoCapture
public
class
VideoCapture
{
protected
final
long
nativeObj
;
protected
VideoCapture
(
long
addr
)
{
nativeObj
=
addr
;
}
//
// C++: VideoCapture::VideoCapture()
//
// javadoc: VideoCapture::VideoCapture()
public
VideoCapture
()
{
nativeObj
=
n_VideoCapture
();
return
;
}
//
// C++: VideoCapture::VideoCapture(int device)
//
// javadoc: VideoCapture::VideoCapture(device)
public
VideoCapture
(
int
device
)
{
nativeObj
=
n_VideoCapture
(
device
);
return
;
}
//
// C++: double VideoCapture::get(int propId)
//
/**
* Returns the specified "VideoCapture" property.
*
* Note: When querying a property that is not supported by the backend used by
* the "VideoCapture" class, value 0 is returned.
*
* @param propId property identifier; it can be one of the following:
* * CV_CAP_PROP_FRAME_WIDTH width of the frames in the video stream.
* * CV_CAP_PROP_FRAME_HEIGHT height of the frames in the video stream.
*
* @see <a href="http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#videocapture-get">org.opencv.highgui.VideoCapture.get</a>
*/
public
double
get
(
int
propId
)
{
double
retVal
=
n_get
(
nativeObj
,
propId
);
return
retVal
;
}
public
List
<
Size
>
getSupportedPreviewSizes
()
{
String
[]
sizes_str
=
n_getSupportedPreviewSizes
(
nativeObj
).
split
(
","
);
List
<
Size
>
sizes
=
new
LinkedList
<
Size
>();
for
(
String
str
:
sizes_str
)
{
String
[]
wh
=
str
.
split
(
"x"
);
sizes
.
add
(
new
Size
(
Double
.
parseDouble
(
wh
[
0
]),
Double
.
parseDouble
(
wh
[
1
])));
}
return
sizes
;
}
//
// C++: bool VideoCapture::grab()
//
// javadoc: VideoCapture::grab()
public
boolean
grab
()
{
boolean
retVal
=
n_grab
(
nativeObj
);
return
retVal
;
}
//
// C++: bool VideoCapture::isOpened()
//
// javadoc: VideoCapture::isOpened()
public
boolean
isOpened
()
{
boolean
retVal
=
n_isOpened
(
nativeObj
);
return
retVal
;
}
//
// C++: bool VideoCapture::open(int device)
//
// javadoc: VideoCapture::open(device)
public
boolean
open
(
int
device
)
{
boolean
retVal
=
n_open
(
nativeObj
,
device
);
return
retVal
;
}
//
// C++: bool VideoCapture::read(Mat image)
//
// javadoc: VideoCapture::read(image)
public
boolean
read
(
Mat
image
)
{
boolean
retVal
=
n_read
(
nativeObj
,
image
.
nativeObj
);
return
retVal
;
}
//
// C++: void VideoCapture::release()
//
// javadoc: VideoCapture::release()
public
void
release
()
{
n_release
(
nativeObj
);
return
;
}
//
// C++: bool VideoCapture::retrieve(Mat image, int channel = 0)
//
// javadoc: VideoCapture::retrieve(image, channel)
public
boolean
retrieve
(
Mat
image
,
int
channel
)
{
boolean
retVal
=
n_retrieve
(
nativeObj
,
image
.
nativeObj
,
channel
);
return
retVal
;
}
// javadoc: VideoCapture::retrieve(image)
public
boolean
retrieve
(
Mat
image
)
{
boolean
retVal
=
n_retrieve
(
nativeObj
,
image
.
nativeObj
);
return
retVal
;
}
//
// C++: bool VideoCapture::set(int propId, double value)
//
/**
* Sets a property in the "VideoCapture".
*
* @param propId property identifier; it can be one of the following:
* * CV_CAP_PROP_FRAME_WIDTH width of the frames in the video stream.
* * CV_CAP_PROP_FRAME_HEIGHT height of the frames in the video stream.
* @param value value of the property.
*
* @see <a href="http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#videocapture-set">org.opencv.highgui.VideoCapture.set</a>
*/
public
boolean
set
(
int
propId
,
double
value
)
{
boolean
retVal
=
n_set
(
nativeObj
,
propId
,
value
);
return
retVal
;
}
@Override
protected
void
finalize
()
throws
Throwable
{
n_delete
(
nativeObj
);
super
.
finalize
();
}
// C++: VideoCapture::VideoCapture()
private
static
native
long
n_VideoCapture
();
// C++: VideoCapture::VideoCapture(string filename)
private
static
native
long
n_VideoCapture
(
java
.
lang
.
String
filename
);
// C++: VideoCapture::VideoCapture(int device)
private
static
native
long
n_VideoCapture
(
int
device
);
// C++: double VideoCapture::get(int propId)
private
static
native
double
n_get
(
long
nativeObj
,
int
propId
);
// C++: bool VideoCapture::grab()
private
static
native
boolean
n_grab
(
long
nativeObj
);
// C++: bool VideoCapture::isOpened()
private
static
native
boolean
n_isOpened
(
long
nativeObj
);
// C++: bool VideoCapture::open(string filename)
private
static
native
boolean
n_open
(
long
nativeObj
,
java
.
lang
.
String
filename
);
// C++: bool VideoCapture::open(int device)
private
static
native
boolean
n_open
(
long
nativeObj
,
int
device
);
// C++: bool VideoCapture::read(Mat image)
private
static
native
boolean
n_read
(
long
nativeObj
,
long
image_nativeObj
);
// C++: void VideoCapture::release()
private
static
native
void
n_release
(
long
nativeObj
);
// C++: bool VideoCapture::retrieve(Mat image, int channel = 0)
private
static
native
boolean
n_retrieve
(
long
nativeObj
,
long
image_nativeObj
,
int
channel
);
private
static
native
boolean
n_retrieve
(
long
nativeObj
,
long
image_nativeObj
);
// C++: bool VideoCapture::set(int propId, double value)
private
static
native
boolean
n_set
(
long
nativeObj
,
int
propId
,
double
value
);
private
static
native
String
n_getSupportedPreviewSizes
(
long
nativeObj
);
// native support for java finalize()
private
static
native
void
n_delete
(
long
nativeObj
);
}
modules/java/test/src/org/opencv/test/OpenCVTestCase.java
View file @
35cb59bb
...
...
@@ -97,7 +97,7 @@ public class OpenCVTestCase extends TestCase {
super
.
setUp
();
try
{
System
.
loadLibrary
(
"opencv_java"
);
System
.
loadLibrary
(
Core
.
NATIVE_LIBRARY_NAME
);
}
catch
(
SecurityException
e
)
{
System
.
out
.
println
(
e
.
toString
());
System
.
exit
(-
1
);
...
...
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