|
|
@@ -30,33 +30,7 @@ |
|
|
* V4L2_PIX_FMT_* and AV_PIX_FMT_* |
|
|
* V4L2_PIX_FMT_* and AV_PIX_FMT_* |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
|
|
|
#undef __STRICT_ANSI__ //workaround due to broken kernel headers |
|
|
|
|
|
#include "config.h" |
|
|
|
|
|
#include "libavformat/internal.h" |
|
|
|
|
|
#include <unistd.h> |
|
|
|
|
|
#include <fcntl.h> |
|
|
|
|
|
#include <sys/ioctl.h> |
|
|
|
|
|
#include <sys/mman.h> |
|
|
|
|
|
#include <sys/time.h> |
|
|
|
|
|
#if HAVE_SYS_VIDEOIO_H |
|
|
|
|
|
#include <sys/videoio.h> |
|
|
|
|
|
#else |
|
|
|
|
|
#if HAVE_ASM_TYPES_H |
|
|
|
|
|
#include <asm/types.h> |
|
|
|
|
|
#endif |
|
|
|
|
|
#include <linux/videodev2.h> |
|
|
|
|
|
#endif |
|
|
|
|
|
#include "libavutil/atomic.h" |
|
|
|
|
|
#include "libavutil/avassert.h" |
|
|
|
|
|
#include "libavutil/imgutils.h" |
|
|
|
|
|
#include "libavutil/log.h" |
|
|
|
|
|
#include "libavutil/opt.h" |
|
|
|
|
|
#include "avdevice.h" |
|
|
|
|
|
#include "timefilter.h" |
|
|
|
|
|
#include "libavutil/parseutils.h" |
|
|
|
|
|
#include "libavutil/pixdesc.h" |
|
|
|
|
|
#include "libavutil/time.h" |
|
|
|
|
|
#include "libavutil/avstring.h" |
|
|
|
|
|
|
|
|
#include "v4l2-common.h" |
|
|
|
|
|
|
|
|
#if CONFIG_LIBV4L2 |
|
|
#if CONFIG_LIBV4L2 |
|
|
#include <libv4l2.h> |
|
|
#include <libv4l2.h> |
|
|
@@ -128,45 +102,6 @@ struct buff_data { |
|
|
int index; |
|
|
int index; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
struct fmt_map { |
|
|
|
|
|
enum AVPixelFormat ff_fmt; |
|
|
|
|
|
enum AVCodecID codec_id; |
|
|
|
|
|
uint32_t v4l2_fmt; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static struct fmt_map fmt_conversion_table[] = { |
|
|
|
|
|
//ff_fmt codec_id v4l2_fmt |
|
|
|
|
|
{ AV_PIX_FMT_YUV420P, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV420 }, |
|
|
|
|
|
{ AV_PIX_FMT_YUV420P, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YVU420 }, |
|
|
|
|
|
{ AV_PIX_FMT_YUV422P, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV422P }, |
|
|
|
|
|
{ AV_PIX_FMT_YUYV422, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUYV }, |
|
|
|
|
|
{ AV_PIX_FMT_UYVY422, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_UYVY }, |
|
|
|
|
|
{ AV_PIX_FMT_YUV411P, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV411P }, |
|
|
|
|
|
{ AV_PIX_FMT_YUV410P, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV410 }, |
|
|
|
|
|
{ AV_PIX_FMT_YUV410P, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YVU410 }, |
|
|
|
|
|
{ AV_PIX_FMT_RGB555LE,AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB555 }, |
|
|
|
|
|
{ AV_PIX_FMT_RGB555BE,AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB555X }, |
|
|
|
|
|
{ AV_PIX_FMT_RGB565LE,AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB565 }, |
|
|
|
|
|
{ AV_PIX_FMT_RGB565BE,AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB565X }, |
|
|
|
|
|
{ AV_PIX_FMT_BGR24, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_BGR24 }, |
|
|
|
|
|
{ AV_PIX_FMT_RGB24, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB24 }, |
|
|
|
|
|
{ AV_PIX_FMT_BGR0, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_BGR32 }, |
|
|
|
|
|
{ AV_PIX_FMT_0RGB, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB32 }, |
|
|
|
|
|
{ AV_PIX_FMT_GRAY8, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_GREY }, |
|
|
|
|
|
#ifdef V4L2_PIX_FMT_Y16 |
|
|
|
|
|
{ AV_PIX_FMT_GRAY16LE,AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_Y16 }, |
|
|
|
|
|
#endif |
|
|
|
|
|
{ AV_PIX_FMT_NV12, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_NV12 }, |
|
|
|
|
|
{ AV_PIX_FMT_NONE, AV_CODEC_ID_MJPEG, V4L2_PIX_FMT_MJPEG }, |
|
|
|
|
|
{ AV_PIX_FMT_NONE, AV_CODEC_ID_MJPEG, V4L2_PIX_FMT_JPEG }, |
|
|
|
|
|
#ifdef V4L2_PIX_FMT_H264 |
|
|
|
|
|
{ AV_PIX_FMT_NONE, AV_CODEC_ID_H264, V4L2_PIX_FMT_H264 }, |
|
|
|
|
|
#endif |
|
|
|
|
|
#ifdef V4L2_PIX_FMT_CPIA1 |
|
|
|
|
|
{ AV_PIX_FMT_NONE, AV_CODEC_ID_CPIA, V4L2_PIX_FMT_CPIA1 }, |
|
|
|
|
|
#endif |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static int device_open(AVFormatContext *ctx) |
|
|
static int device_open(AVFormatContext *ctx) |
|
|
{ |
|
|
{ |
|
|
struct v4l2_capability cap; |
|
|
struct v4l2_capability cap; |
|
|
@@ -275,49 +210,6 @@ static int first_field(int fd) |
|
|
return 1; |
|
|
return 1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static uint32_t fmt_ff2v4l(enum AVPixelFormat pix_fmt, enum AVCodecID codec_id) |
|
|
|
|
|
{ |
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) { |
|
|
|
|
|
if ((codec_id == AV_CODEC_ID_NONE || |
|
|
|
|
|
fmt_conversion_table[i].codec_id == codec_id) && |
|
|
|
|
|
(pix_fmt == AV_PIX_FMT_NONE || |
|
|
|
|
|
fmt_conversion_table[i].ff_fmt == pix_fmt)) { |
|
|
|
|
|
return fmt_conversion_table[i].v4l2_fmt; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static enum AVPixelFormat fmt_v4l2ff(uint32_t v4l2_fmt, enum AVCodecID codec_id) |
|
|
|
|
|
{ |
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) { |
|
|
|
|
|
if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt && |
|
|
|
|
|
fmt_conversion_table[i].codec_id == codec_id) { |
|
|
|
|
|
return fmt_conversion_table[i].ff_fmt; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return AV_PIX_FMT_NONE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static enum AVCodecID fmt_v4l2codec(uint32_t v4l2_fmt) |
|
|
|
|
|
{ |
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) { |
|
|
|
|
|
if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt) { |
|
|
|
|
|
return fmt_conversion_table[i].codec_id; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return AV_CODEC_ID_NONE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE |
|
|
#if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE |
|
|
static void list_framesizes(AVFormatContext *ctx, int fd, uint32_t pixelformat) |
|
|
static void list_framesizes(AVFormatContext *ctx, int fd, uint32_t pixelformat) |
|
|
{ |
|
|
{ |
|
|
@@ -349,8 +241,8 @@ static void list_formats(AVFormatContext *ctx, int fd, int type) |
|
|
struct v4l2_fmtdesc vfd = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE }; |
|
|
struct v4l2_fmtdesc vfd = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE }; |
|
|
|
|
|
|
|
|
while(!v4l2_ioctl(fd, VIDIOC_ENUM_FMT, &vfd)) { |
|
|
while(!v4l2_ioctl(fd, VIDIOC_ENUM_FMT, &vfd)) { |
|
|
enum AVCodecID codec_id = fmt_v4l2codec(vfd.pixelformat); |
|
|
|
|
|
enum AVPixelFormat pix_fmt = fmt_v4l2ff(vfd.pixelformat, codec_id); |
|
|
|
|
|
|
|
|
enum AVCodecID codec_id = avpriv_fmt_v4l2codec(vfd.pixelformat); |
|
|
|
|
|
enum AVPixelFormat pix_fmt = avpriv_fmt_v4l2ff(vfd.pixelformat, codec_id); |
|
|
|
|
|
|
|
|
vfd.index++; |
|
|
vfd.index++; |
|
|
|
|
|
|
|
|
@@ -825,7 +717,7 @@ static int device_try_init(AVFormatContext *s1, |
|
|
{ |
|
|
{ |
|
|
int ret, i; |
|
|
int ret, i; |
|
|
|
|
|
|
|
|
*desired_format = fmt_ff2v4l(pix_fmt, s1->video_codec_id); |
|
|
|
|
|
|
|
|
*desired_format = avpriv_fmt_ff2v4l(pix_fmt, s1->video_codec_id); |
|
|
|
|
|
|
|
|
if (*desired_format) { |
|
|
if (*desired_format) { |
|
|
ret = device_init(s1, width, height, *desired_format); |
|
|
ret = device_init(s1, width, height, *desired_format); |
|
|
@@ -837,14 +729,14 @@ static int device_try_init(AVFormatContext *s1, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (!*desired_format) { |
|
|
if (!*desired_format) { |
|
|
for (i = 0; i<FF_ARRAY_ELEMS(fmt_conversion_table); i++) { |
|
|
|
|
|
|
|
|
for (i = 0; avpriv_fmt_conversion_table[i].codec_id != AV_CODEC_ID_NONE; i++) { |
|
|
if (s1->video_codec_id == AV_CODEC_ID_NONE || |
|
|
if (s1->video_codec_id == AV_CODEC_ID_NONE || |
|
|
fmt_conversion_table[i].codec_id == s1->video_codec_id) { |
|
|
|
|
|
|
|
|
avpriv_fmt_conversion_table[i].codec_id == s1->video_codec_id) { |
|
|
av_log(s1, AV_LOG_DEBUG, "Trying to set codec:%s pix_fmt:%s\n", |
|
|
av_log(s1, AV_LOG_DEBUG, "Trying to set codec:%s pix_fmt:%s\n", |
|
|
avcodec_get_name(fmt_conversion_table[i].codec_id), |
|
|
|
|
|
(char *)av_x_if_null(av_get_pix_fmt_name(fmt_conversion_table[i].ff_fmt), "none")); |
|
|
|
|
|
|
|
|
avcodec_get_name(avpriv_fmt_conversion_table[i].codec_id), |
|
|
|
|
|
(char *)av_x_if_null(av_get_pix_fmt_name(avpriv_fmt_conversion_table[i].ff_fmt), "none")); |
|
|
|
|
|
|
|
|
*desired_format = fmt_conversion_table[i].v4l2_fmt; |
|
|
|
|
|
|
|
|
*desired_format = avpriv_fmt_conversion_table[i].v4l2_fmt; |
|
|
ret = device_init(s1, width, height, *desired_format); |
|
|
ret = device_init(s1, width, height, *desired_format); |
|
|
if (ret >= 0) |
|
|
if (ret >= 0) |
|
|
break; |
|
|
break; |
|
|
@@ -863,7 +755,7 @@ static int device_try_init(AVFormatContext *s1, |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
*codec_id = fmt_v4l2codec(*desired_format); |
|
|
|
|
|
|
|
|
*codec_id = avpriv_fmt_v4l2codec(*desired_format); |
|
|
av_assert0(*codec_id != AV_CODEC_ID_NONE); |
|
|
av_assert0(*codec_id != AV_CODEC_ID_NONE); |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
@@ -986,7 +878,7 @@ static int v4l2_read_header(AVFormatContext *s1) |
|
|
if ((res = v4l2_set_parameters(s1)) < 0) |
|
|
if ((res = v4l2_set_parameters(s1)) < 0) |
|
|
return res; |
|
|
return res; |
|
|
|
|
|
|
|
|
st->codec->pix_fmt = fmt_v4l2ff(desired_format, codec_id); |
|
|
|
|
|
|
|
|
st->codec->pix_fmt = avpriv_fmt_v4l2ff(desired_format, codec_id); |
|
|
s->frame_size = |
|
|
s->frame_size = |
|
|
avpicture_get_size(st->codec->pix_fmt, s->width, s->height); |
|
|
avpicture_get_size(st->codec->pix_fmt, s->width, s->height); |
|
|
|
|
|
|
|
|
|