I want to control a ptz camera from android,actually i do that in jni and use linux api,the camera is connected to android-tvbox's usb interface directly, ,below is the code:
struct v4l2_ext_control xctrls[1];
struct v4l2_ext_controls ctrls;
memset(xctrls, 0, sizeof xctrls);
memset(&ctrls, 0, sizeof ctrls);
xctrls[0].id = V4L2_CID_PAN_ABSOLUTE;
xctrls[0].value = 20;
ctrls.ctrl_class = V4L2_CTRL_CLASS_CAMERA;
ctrls.count = 1;
ctrls.controls = xctrls;
//xioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
int result = ioctl(fd, VIDIOC_S_CTRL, &ctrls);
//LOGE("Cannot identify:%d , %d, %s", result, errno, strerror (errno));
LOGE("Cannot open '%d': %d, %s", result, errno, strerror (errno));
and it return invalid argument , can anyone tell me which argument is wrong?Or my code is incorrect...
I have solved this problem. Actually, you need to design your Android source code in UVC (USB Video Class) module, and UVC is located in the kernel of the whole android source code.
What's more, you have to cooperate with the camera's vendor, because they have deep insights into the firmware of PTZ cameras, and Android's UVC version should apply to camera firmware, data length and control type (absolute or relative).
Furthermore, Android kernel's version is generally 3.10. When you control camera with absolute control, it may move in one direction but not another one, because the Android UVC control parameters of absolute is unsigned: you should change it to signed parameters.
When you control in relative, it's a little more complicated, for you should add relative control in Android source code because Android kernel in 3.10 does not support it. You can get the Linux kernel patch to add relative movements.
Related
I am developing an Android application based on Qt5.4/QtQuick 2 and opengles 2.
I installed textureinsgnode in order to check how well it runs in my target device(as my app is making massive use of FBOs) and I am getting 18 FPS. I checked on a Samsung SM-T535 and I get around 47/48 FPS, and my application looks like colapsed when trying to make any user action.
I checked the extension available in both devices(my target and Samsung tablet) by:
QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) {
QSet<QByteArray> extensions = QOpenGLContext::currentContext()->extensions();
foreach (QByteArray extension, extensions) {
qDebug() << extension;
}
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setSamples(4);
return new QOpenGLFramebufferObject(size, format);
}
And I am getting a very sort list of extensions in the target device If I compare with Samsung tablet list in the same point:
"GL_OES_rgb8_rgba8"
"GL_EXT_multisampled_render_to_texture" "GL_OES_packed_depth_stencil"
"GL_ARM_rgba8" "GL_OES_vertex_half_float" "GL_OES_EGL_image"
"GL_EXT_discard_framebuffer" "GL_OES_compressed_ETC1_RGB8_texture"
"GL_OES_depth_texture" "GL_KHR_debug" "GL_ARM_mali_shader_binary"
"GL_OES_depth24" "GL_EXT_texture_format_BGRA8888"
"GL_EXT_blend_minmax" "GL_EXT_shader_texture_lod"
"GL_OES_EGL_image_external" "GL_EXT_robustness" "GL_OES_texture_npot"
"GL_OES_depth_texture_cube_map" "GL_ARM_mali_program_binary"
"GL_EXT_debug_marker" "GL_OES_get_program_binary"
"GL_OES_standard_derivatives" "GL_OES_EGL_sync"
I installed an NME(3.4.4, so based in opengl es 1.1) application (BunnyMark) and I can get around 45-48 FPS.
By basing in this tests, I can think the target device is having some problem with opengl es 2 but I am not able to find (I was googleing) on any place what opengl es 2 extension requires Qt5.4 to work properly.
The question: What are the opengl es 2 extensions required by Qt5.4 and is there a way to check it?
I am trying to write a android arm kernel module in which I need to use a virt_to_phys translation of a memory var allocated using _kmalloc.
I do know that I can use the macro virt_to_physc to do this task. However, I dont have the specifically full kernel source, and beacuse virt_to_physc is a macro
I can't get a function address reading kallsyms to use in my module , so I would like to find another way to do this task.
I've been trying to do it using MMU (registers ATS1Cxx and PAR) to perform V=>P as Iam working in an ARMv7 proccessor but I couldnt make it work.
That's my test code...
int hello_init_module(void) {
printk("Virtual MEM:0x%X \n", allocated_buf);
//Trying to get the physc mem
asm("\t mcr p15, 0, %[value], c7, c8, 2\n"
"\t isb\n"
\t mrc p15, 0, %[result], c7, c4, 0\n" : [result]"=r" (pa) : [value]"r" (allocated_buf));
printk("Physical using MMU : %x\n", pa );
//This show the right address, but I wanna do it without calling the macro.
printk("Physical using virt_2_physc: 0x%X",virt_to_phys((int *) allocated_buf);)
}
What Iam actually doing is developing a module that is intended to work in two devices with the same 3.4.10 kernel but different memory arquitectures,
I can make the module works as they have the same VER_MAGIC and functions crc, so the module load perfectly in both devices.
The main problem is that because of diferences in their arquitecture, PAGE_OFFSET and PHYS_OFFSET actually change in both of them.
So, I've wondering if there is a way to make the translation without define this values as constant in my module.That's what I tried using MMU to perform V=>P , but MMU hasnt worked in my case, it always returns 0x1F.
According to cat /proc/cpuinfo . Iam working with a
Processor : ARMv7 Processor rev 0 (v7l)
processor : 0
Features : swp half thumb fastmult vfp edsp neon vfpv3 tls
CPU implementer : 0x51
CPU architecture: 7
If it's not possible to do it using MMU as alternative way of using virt_to_phys.
Does somebody know other way to do it?
i am trying to capture video on android using v4l2 under jni. i found some guide and followed the step:
fd = open("/dev/video0", O_RDWR);
/* init part */
ioctl(fd, VIDIOC_QUERYCAP, &caps);
ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc);
ioctl(fd, VIDIOC_S_FMT, &fmt);
ioctl(fd, VIDIOC_REQBUFS, &req);
ioctl(fd, VIDIOC_QUERYBUF, &buf);
ioctl(fd, VIDIOC_QBUF, &buf);
/* capture part */
FILE *fp = fopen("/sdcard/img.yuv", "wb");
for (i = 0; i < 20; i++)
{
ioctl(fd, VIDIOC_DQBUF, &buf);
fwrite(buffers[buf.index].start, 1, buf.bytesused, fp);
ioctl(fd, VIDIOC_QBUF, &buf);
}
fclose(fp);
this is the main structure of my code. all the function run correctly and return 0. however, when i open the output file with binary viewer, i found that all the data is 0.
is there any problem with my code? i got confused because all the functions returned 0.
Thanks!!
You are using an array called buffers[]. But I can't see where it's declared or what it stands for. If there is no code missing above, you will always get zeros cause you are writing buffer[] to the file and not the stuff you get from v4l2.
Further more, the initial values of caps, fmtdesc, fmt, req and buf prior to the ioctl command would be interesting too. Depending on their inital values, you will have different communication interfaces. Issues could be hidden in these parts.
As you wrote in your question, all ioctl commands would return 0, there should be no error. If everything behaves as expected. Another way to check for issues is calling
perror("<your comment or hint to line above>");
after each ioctl command. This would print you more information about errors on your std-out. ( more details about perror can be found in this thread When should I use perror("...") and fprintf(stderr, "...")?)
Are you trying to get the images from the camera? (on some phones video0 you used above is the back cam) On some android devices the camera has to be started by complex procedure using other device drivers besides videoXY. And trying to get the images from video0 while the official camera app is running might be difficult. The official v4l2 api says:
V4L2 drivers should not support multiple applications reading or writing the same data stream on a device by copying buffers, time multiplexing or similar means. This is better handled by a proxy application in user space.
From: http://linuxtv.org/downloads/v4l-dvb-apis/common.html#idp18553208
Can you post more (detailed) code? I might be able to help, as I'm doing very similar stuff.
To be able to reproduce it, it would be very interesting with which android device you are working (type / model number / android version).
I have been trying to capture audio, within a native linux program running on an Android device via adb shell.
Since I seemed to be getting only (very quiet) noise, i.e. no actual signal (interestingly, an Android/Java program doing similar did show there was a signal on that input),
I executed alsa_amixer, which had one entry that looked like the right one:
Simple mixer control 'Capture',0
Capabilities: cvolume cswitch penum
Capture channels: Front Left - Front Right
Limits: Capture 0 - 63
Front Left: Capture 31 [49%] [0.00dB] [off]
Front Right: Capture 31 [49%] [0.00dB] [off]
"off". That would explain the noise.
So I looked for examples of how to use alsa_amixer to unmute the channels, I found different suggestions for parameters like "49% on" or "49% unmute", or just "unmute" none of which works. (if the volume% is left out, it says "Invalid command!", otherwise, the volume is set, but the on/unmute is ignored)
I also searched how to do this programatically (which I'll ultimately need to do, although the manual approach would be helpful for now), but wasn't too lucky there.
The only ALSA lib command I found which sounds like it could do something like that was "snd_mixer_selem_set_capture_switch_all", but the docs don't day what the parameter does (1/0 is not on/off, I tried that ;) )
The manual approach to set these things via alsa_amixer does work - but only if android is built with the 'BoardConfigCommon.mk' modified, at the entry: BOARD_USES_ALSA_AUDIO := false, instead of true.
Yeah, this will probably disable ALSA for android, which is why it wouldn't meddle with the mixer settings anymore.
To you android programmers out there, note that this is a very niche use case of course, as was to be expected by my original post to begin with.
This is not what most people would want to do.
I just happen to tinker with an android device here in unusual ways ;-)
Just posting the code as question giver suggested, also don't like external links.
#include <alsa/asoundlib.h>
int main()
{
snd_mixer_t *handle;
snd_mixer_selem_id_t *sid;
snd_mixer_open(&handle, 0);
snd_mixer_attach(handle, "default");
snd_mixer_selem_register(handle, NULL, NULL);
snd_mixer_load(handle);
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_id_set_index(sid, 0);
snd_mixer_selem_id_set_name(sid, "Capture");
snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);
snd_mixer_selem_set_capture_switch_all(elem, 0);
snd_mixer_selem_set_capture_dB_all(elem, 0, 0);
snd_mixer_close(handle);
}
I have an IP camera which is streaming video in MJPEG format. Now my aim is to receive it and display it in my own custom android app. For this I have three programming alternatives on android platform :
Using inbuilt Anrdroid MediaPlayer class
Using FFMPEG library in native C and accessing it through JNI
Using GStreamer port on android to receive the stream
So please suggest a better solution?
I have no experience with FFMPEG or GStreamer. So what is the feasibility of doing this?
Use gstreamer for it.
I have used gstreamer at beagleboard which has 1GHz processor for taking image from 2 cameras in 30 fps with very low CPU processing power.
Gstreamer able to merge images, add strings, change formats. And presents you what you want easily in stream. The only thing you need to do is adding black boxes each other.
You can add blackboxes with both dynamically and statically.
If you are not going to change your stream depends on input at your program I suggest to use static one. But I am not sure if it works at android..
To test 3rd option (gstreamer) you can use this app: https://play.google.com/store/apps/details?id=pl.effisoft.rpicamviewer2. You can also open gstreamer preview from your code using following code:
Intent intent = new Intent("pl.effisoft.rpicamviewer2.PREVIEW");
int camera =0;
//--------- Basic settings
intent.putExtra("full_screen", true);
intent.putExtra("name"+camera, "My pipeline name");
intent.putExtra("host"+camera, "192.168.0.1");
intent.putExtra("port"+camera, 5000);
intent.putExtra("description"+camera, "My pipeline description");
intent.putExtra("uuid"+camera, UUID.randomUUID().toString() );
intent.putExtra("aspectRatio"+camera, 1.6);
intent.putExtra("autoplay"+camera, true);
//--------- Enable advanced mode
intent.putExtra("advanced"+camera, true); //when advanced=true, then custom_pipeline will be played
//when advanced=false, then pipeline will be generated from host, port (use only for backward compatibility with previous versions)
intent.putExtra("custom_pipeline"+camera, "videotestsrc ! warptv ! autovideosink");
//--------- Enable application extra features
intent.putExtra("extraFeaturesEnabled"+camera, false);
//--------- Add autoaudiosink to featured pipeline
intent.putExtra("extraFeaturesSoundEnabled"+camera, false);
//--------- Scale Video Stream option
intent.putExtra("extraResizeVideoEnabled"+camera, false);
intent.putExtra("width"+camera, 320); //used only when extraResizeVideoEnabled=true
intent.putExtra("height"+camera, 200); //used only when extraResizeVideoEnabled=true
//--------- Add plugins
ArrayList<String> plugins = new ArrayList<String>();
intent.putExtra("plugins"+camera, plugins);
intent.setPackage("pl.effisoft.rpicamviewer2");
startActivityForResult(intent, 0);