Devider писал(а): ↑04.11.2013 20:01
Нет, это на x86_64,а теперь новая итерация, перенести это все на arm. Рад, что возражений нет, но захват не работает с приведенными выше ошибками.
На счет модулей, все, что мне показалось необходимымя вроде включил в ядро.
С использованием GStreamer мы сделали полноценную камеру на базе ARM FreeScale iMX538, поэтому могу точно утверждать, что GStreamer работает на ARM как с USB-камерами, так и с CMOS-сенсорами.
Возможно Вам поможет это:
Код: Выделить всё
#!/bin/sh
GS=gst-launch
DEF_PORT=5000
DEF_CODEC=h264
DEF_RES=640x480
usage() {
echo -e "\n$0 [OPTIONS]\n"
echo -e "\t-m run mode [server, client]"
echo -e "\t-c codec (h264, mpeg4, h263, jpeg, js) [$DEF_CODEC]"
echo -e "\t\tjpeg - hardware encode, js - software encode"
echo -e "\t-a destination or source address"
echo -e "\t\tnot set on client if server send on client address"
echo -e "\t-p destination or source port [$DEF_PORT]"
echo -e "\t-r resolution [$DEF_RES]"
echo -e "\t-h this help"
}
run_server()
{
if [ -z $ADDRESS ]; then
echo "Detination address can't be empty!"
echo
fi
W=`echo $RESOLUTION | cut -d'x' -f1`
H=`echo $RESOLUTION | cut -d'x' -f2`
CMD="$GS -v v4l2src device=/dev/video0"
CMD=$CMD" ! video/x-raw-yuv,width=$W,height=$H"
CMD=$CMD" ! mfw_ipucsc"
if [ "$CODEC" != js ]; then
CMD=$CMD" ! mfw_vpuencoder width=$W height=$H"
elif [ "$CODEC" = js ]; then
CMD=$CMD" ! jpegenc"
fi
if [ "$CODEC" = h264 ]; then
CMD=$CMD" codec-type=std_avc ! rtph264pay pt=96"
elif [ "$CODEC" = mpeg4 ]; then
CMD=$CMD" codec-type=std_mpeg4 ! rtpmp4vpay send-config=true"
elif [ "$CODEC" = h263 ]; then
CMD=$CMD" codec-type=std_h263 ! rtph263pay pt=96"
elif [ "$CODEC" = jpeg -o "$CODEC" = js ]; then
[ "$CODEC" = jpeg ] && CMD=$CMD" codec-type=std_mjpg"
CMD=$CMD" ! rtpjpegpay type=26"
else
echo "Unknow codec $CODEC"
exit
fi
CMD=$CMD" ! udpsink host=$ADDRESS port=$PORT sync=false"
echo $CMD
$CMD
}
run_client()
{
CMD="$GS -v udpsrc"
[ -z "$ADDRESS" ] || CMD=$CMD" multicast-group=$ADDRESS"
CMD=$CMD" port=$PORT "
CMD=$CMD" caps=\"application/x-rtp, media=(string)video,"
CMD=$CMD" clock-rate=(int)90000,"
if [ "$CODEC" = h264 ]; then
CMD=$CMD" payload=(int)96, encoding-name=(string)H264\""
CMD=$CMD" ! rtph264depay ! ffdec_h264"
elif [ "$CODEC" = mpeg4 ]; then
CMD=$CMD" payload=(int)96, profile-level-id=(string)6,"
CMD=$CMD" encoding-name=(string)MP4V-ES\""
CMD=$CMD" ! rtpmp4vdepay ! ffdec_mpeg4"
elif [ "$CODEC" = h263 ]; then
CMD=$CMD" payload=(int)34, encoding-name=(string)H263\""
CMD=$CMD" ! rtph263depay ! ffdec_h263"
elif [ "$CODEC" = jpeg -o "$CODEC" = js ]; then
CMD=$CMD" payload=(int)96, encoding-name=(string)JPEG\""
CMD=$CMD" ! rtpjpegdepay ! ffdec_mjpeg"
else
echo "Unknow codec $CODEC"
exit
fi
CMD=$CMD" ! xvimagesink"
echo $CMD
$CMD
}
if [ $# -eq 0 ]; then
usage
exit
fi
while getopts "m:c:a:p:r:hd" opt; do
case "$opt" in
m) MODE=$OPTARG;;
c) CODEC=$OPTARG;;
a) ADDRESS=$OPTARG;;
p) PORT=$OPTARG;;
r) RESOLUTION=$OPTARG;;
h|\?|*) usage; exit;;
esac
done
PORT=${PORT:-$DEF_PORT}
CODEC=${CODEC:-$DEF_CODEC}
RESOLUTION=${RESOLUTION:-$DEF_RES}
if [ "$MODE" = server ]; then
run_server $CODEC $RESOLUTION $ADDRESS $PORT
elif [ "$MODE" = client ]; then
run_client $CODEC $ADDRESS $PORT
else
usage
fi
Этим скриптом я запускал тестовый pipeline на плате. Конечно его надо будет чуть "подрихтовать" под Ваши реалии
Если угодно, то вот пример захвата с матриц, с USB-камерами не пробовал:
Код: Выделить всё
#include <stdio.h>
#include <argp.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#define FPS 30
#define DEVICE "/dev/video0"
#define NUMBER 100
#define BUFFER 3
#define WIDTH 1280
#define HEIGHT 720
const char *argp_program_version = "fpsmeter 0.1.1\n"
"Compiled " __DATE__ " " __TIME__;
static char doc[] = "Capture frames meter";
static struct argp_option options[] = {
{"device", 'd', "DEVICE", 0, "Capture device [" DEVICE "]", 0},
{"fps", 'f', "FPS", 0, "Set framerate [30]", 0},
{"number", 'n', "NUMBER", 0, "Number capture frames [100]", 0},
{"resolution", 'r', "RESOL", 0, "Captured resolution [1280x720]", 0},
{"mode", 'm', "MODE", 0, "Captured mode [0]", 0},
{0, 0, 0, 0, 0, 0}
};
struct arguments {
char *device;
unsigned char fps;
unsigned char mode;
unsigned short width;
unsigned short height;
unsigned int number;
};
static error_t parse_opt(int key, char *arg, struct argp_state *state)
{
struct arguments *a = state->input;
switch (key) {
case 'd':
a->device = arg;
break;
case 'f':
a->fps = (unsigned char)atoi(arg);
break;
case 'n':
a->number = (unsigned int)atoi(arg);
break;
case 'r':
if (sscanf(arg, "%hux%hu", &a->width, &a->height) != 2)
argp_error(state, "Failed parse resolution %s!\n", arg);
break;
case 'm':
a->mode = (unsigned char)atoi(arg);
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static struct argp argp = {options, parse_opt, 0, doc, 0, 0, 0};
typedef struct {
__u32 length;
__u32 offset;
void *data;
} buf_info;
int main(int argc, char *argv[])
{
struct arguments arg;
struct v4l2_format fmt;
struct v4l2_streamparm parm;
struct v4l2_crop crop;
struct v4l2_requestbuffers req;
struct v4l2_buffer buf;
enum v4l2_buf_type type;
struct timeval tv[2];
int fd = -1;
unsigned char i;
buf_info frames[BUFFER];
unsigned int cap_number = 0;
memset(&arg, 0, sizeof(arg));
memset(frames, 0, sizeof(buf_info) * BUFFER);
arg.device = DEVICE;
arg.fps = FPS;
arg.number = NUMBER;
arg.width = WIDTH;
arg.height = HEIGHT;
arg.mode = 0;
argp_parse(&argp, argc, argv, 0, 0, &arg);
fd = open(arg.device, O_RDWR);
if (fd <= 0) {
fprintf(stderr, "Failed open %s!\n", arg.device);
return -1;
}
// конфигурирование
memset(&parm, 0, sizeof(parm));
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
parm.parm.capture.timeperframe.numerator = arg.fps;
parm.parm.capture.timeperframe.denominator = 1;
parm.parm.capture.capturemode = arg.mode;
if (ioctl(fd, VIDIOC_S_PARM, &parm)) {
fprintf(stderr, "Failed VIDIOC_S_PARM!\n");
goto ERROR;
}
memset(&crop, 0, sizeof(crop));
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
crop.c.width = arg.width;
crop.c.height = arg.height;
crop.c.top = 0;
crop.c.left = 0;
if (ioctl(fd, VIDIOC_S_CROP, &crop)) {
fprintf(stderr, "Failed VIDIOC_S_CROP!\n");
goto ERROR;
}
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
fmt.fmt.pix.width = arg.width;
fmt.fmt.pix.height = arg.height;
if (ioctl(fd, VIDIOC_S_FMT, &fmt)) {
fprintf(stderr, "Failed VIDIOC_S_FMT!\n");
goto ERROR;
}
memset(&req, 0, sizeof(req));
req.count = BUFFER;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd, VIDIOC_REQBUFS, &req)) {
fprintf(stderr, "Failed VIDIOC_REQBUFS!\n");
goto ERROR;
}
// запуск захвата
for (i = 0; i < BUFFER; i++) {
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.index = i;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf)) {
fprintf(stderr, "Failed VIDIOC_QUERYBUF!\n");
goto ERROR;
}
frames[i].length = buf.length;
frames[i].offset = buf.m.offset;
frames[i].data = mmap(NULL, buf.length,
PROT_READ | PROT_WRITE, MAP_SHARED, fd,
(off_t)buf.m.offset);
if (NULL == frames[i].data) {
fprintf(stderr, "Failed mmap!\n");
goto ERROR;
}
}
for (i = 0; i < BUFFER; i++) {
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
buf.m.offset = frames[i].offset;
if (ioctl(fd, VIDIOC_QBUF, &buf)) {
fprintf(stderr, "Failed VIDIOC_QBUF!\n");
goto MMAP;
}
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_STREAMON, &type)) {
fprintf(stderr, "Failed VIDIOC_STREAMON!\n");
goto MMAP;
}
// получение кадров
memset(tv, 0, 2 * sizeof(struct timeval));
gettimeofday(&tv[0], NULL);
while (cap_number != arg.number) {
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (ioctl (fd, VIDIOC_DQBUF, &buf)) {
fprintf(stderr, "Failed VIDIOC_DQBUF!\n");
goto MMAP;
}
if (ioctl(fd, VIDIOC_QBUF, &buf)) {
fprintf(stderr, "Failed VIDIOC_QBUF!\n");
goto MMAP;
}
cap_number++;
}
gettimeofday(&tv[1], NULL);
fprintf(stderr, "Captured %u frames in %lu usec (%.02f FPS)\n",
arg.number,
(tv[1].tv_sec * 1000000 + tv[1].tv_usec) -
(tv[0].tv_sec * 1000000 + tv[0].tv_usec),
(float)arg.number /
(float)(((tv[1].tv_sec * 1000000 + tv[1].tv_usec) -
(tv[0].tv_sec * 1000000 + tv[0].tv_usec)) / 1000000));
// остановка потока
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_STREAMOFF, &type)) {
fprintf(stderr, "Failed VIDIOC_STREAMOFF!\n");
goto ERROR;
}
for (i = 0; i < BUFFER; i++)
munmap(frames[i].data, frames[i].length);
close(fd);
return EXIT_SUCCESS;
MMAP:
for (i = 0; i < BUFFER; i++)
munmap(frames[i].data, frames[i].length);
ERROR:
close(fd);
return -EXIT_FAILURE;
}
К сожалению, или радости, мне не повезло и я не имел возможности использовать полностью готовый софт, поэтому могу только порекомендовать разбить проблему на меньшие этапы - сперва добиться захвата, потом добавить кодирование и на финальном этапе трансляцию или запись в файл, смотря что Вам нужно.
И не забывайте обращаться к документации производителя, как бы она не была скудна всё же это лучше чем ничего. Так же очень часто ответ можно в исходникам, но это требует уже более кропотливой работы и часто надо знать где и что искать.