mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-04-23 07:26:43 +00:00
avcodec/v4l2_m2m: decouple v4l2_m2m helpers from AVCodecContext
This will allow re-use of the m2m backend with AVFilterContext Signed-off-by: Aman Gupta <aman@tmm1.net>
This commit is contained in:
parent
d61cf1b1eb
commit
c0c7946196
@ -48,9 +48,9 @@ static inline V4L2m2mContext *ctx_to_m2mctx(V4L2Context *ctx)
|
|||||||
container_of(ctx, V4L2m2mContext, capture);
|
container_of(ctx, V4L2m2mContext, capture);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline AVCodecContext *logger(V4L2Context *ctx)
|
static inline AVClass *logger(V4L2Context *ctx)
|
||||||
{
|
{
|
||||||
return ctx_to_m2mctx(ctx)->avctx;
|
return ctx_to_m2mctx(ctx)->priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int v4l2_get_width(struct v4l2_format *fmt)
|
static inline unsigned int v4l2_get_width(struct v4l2_format *fmt)
|
||||||
@ -96,7 +96,7 @@ static inline int v4l2_get_framesize_compressed(V4L2Context* ctx, int width, int
|
|||||||
const int SZ_4K = 0x1000;
|
const int SZ_4K = 0x1000;
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
if (av_codec_is_decoder(s->avctx->codec))
|
if (s->avctx && av_codec_is_decoder(s->avctx->codec))
|
||||||
return ((width * height * 3 / 2) / 2) + 128;
|
return ((width * height * 3 / 2) / 2) + 128;
|
||||||
|
|
||||||
/* encoder */
|
/* encoder */
|
||||||
@ -193,6 +193,7 @@ static int v4l2_handle_event(V4L2Context *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (reinit) {
|
if (reinit) {
|
||||||
|
if (s->avctx)
|
||||||
ret = ff_set_dimensions(s->avctx, s->capture.width, s->capture.height);
|
ret = ff_set_dimensions(s->avctx, s->capture.width, s->capture.height);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
av_log(logger(ctx), AV_LOG_WARNING, "update avcodec height and width\n");
|
av_log(logger(ctx), AV_LOG_WARNING, "update avcodec height and width\n");
|
||||||
|
@ -63,6 +63,7 @@ static inline int v4l2_mplane_video(struct v4l2_capability *cap)
|
|||||||
static int v4l2_prepare_contexts(V4L2m2mContext* s, int probe)
|
static int v4l2_prepare_contexts(V4L2m2mContext* s, int probe)
|
||||||
{
|
{
|
||||||
struct v4l2_capability cap;
|
struct v4l2_capability cap;
|
||||||
|
void *log_ctx = s->priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
s->capture.done = s->output.done = 0;
|
s->capture.done = s->output.done = 0;
|
||||||
@ -76,7 +77,7 @@ static int v4l2_prepare_contexts(V4L2m2mContext* s, int probe)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
av_log(s->avctx, probe ? AV_LOG_DEBUG : AV_LOG_INFO,
|
av_log(log_ctx, probe ? AV_LOG_DEBUG : AV_LOG_INFO,
|
||||||
"driver '%s' on card '%s' in %s mode\n", cap.driver, cap.card,
|
"driver '%s' on card '%s' in %s mode\n", cap.driver, cap.card,
|
||||||
v4l2_mplane_video(&cap) ? "mplane" :
|
v4l2_mplane_video(&cap) ? "mplane" :
|
||||||
v4l2_splane_video(&cap) ? "splane" : "unknown");
|
v4l2_splane_video(&cap) ? "splane" : "unknown");
|
||||||
@ -98,6 +99,7 @@ static int v4l2_prepare_contexts(V4L2m2mContext* s, int probe)
|
|||||||
|
|
||||||
static int v4l2_probe_driver(V4L2m2mContext* s)
|
static int v4l2_probe_driver(V4L2m2mContext* s)
|
||||||
{
|
{
|
||||||
|
void *log_ctx = s->priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
s->fd = open(s->devname, O_RDWR | O_NONBLOCK, 0);
|
s->fd = open(s->devname, O_RDWR | O_NONBLOCK, 0);
|
||||||
@ -110,20 +112,20 @@ static int v4l2_probe_driver(V4L2m2mContext* s)
|
|||||||
|
|
||||||
ret = ff_v4l2_context_get_format(&s->output, 1);
|
ret = ff_v4l2_context_get_format(&s->output, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
av_log(s->avctx, AV_LOG_DEBUG, "v4l2 output format not supported\n");
|
av_log(log_ctx, AV_LOG_DEBUG, "v4l2 output format not supported\n");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ff_v4l2_context_get_format(&s->capture, 1);
|
ret = ff_v4l2_context_get_format(&s->capture, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
av_log(s->avctx, AV_LOG_DEBUG, "v4l2 capture format not supported\n");
|
av_log(log_ctx, AV_LOG_DEBUG, "v4l2 capture format not supported\n");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (close(s->fd) < 0) {
|
if (close(s->fd) < 0) {
|
||||||
ret = AVERROR(errno);
|
ret = AVERROR(errno);
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "failure closing %s (%s)\n", s->devname, av_err2str(AVERROR(errno)));
|
av_log(log_ctx, AV_LOG_ERROR, "failure closing %s (%s)\n", s->devname, av_err2str(AVERROR(errno)));
|
||||||
}
|
}
|
||||||
|
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
@ -133,7 +135,7 @@ done:
|
|||||||
|
|
||||||
static int v4l2_configure_contexts(V4L2m2mContext* s)
|
static int v4l2_configure_contexts(V4L2m2mContext* s)
|
||||||
{
|
{
|
||||||
void *log_ctx = s->avctx;
|
void *log_ctx = s->priv;
|
||||||
int ret;
|
int ret;
|
||||||
struct v4l2_format ofmt, cfmt;
|
struct v4l2_format ofmt, cfmt;
|
||||||
|
|
||||||
@ -174,7 +176,7 @@ static int v4l2_configure_contexts(V4L2m2mContext* s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* decoder's buffers need to be updated at a later stage */
|
/* decoder's buffers need to be updated at a later stage */
|
||||||
if (!av_codec_is_decoder(s->avctx->codec)) {
|
if (!s->avctx || !av_codec_is_decoder(s->avctx->codec)) {
|
||||||
ret = ff_v4l2_context_init(&s->capture);
|
ret = ff_v4l2_context_init(&s->capture);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
av_log(log_ctx, AV_LOG_ERROR, "no v4l2 capture context's buffers\n");
|
av_log(log_ctx, AV_LOG_ERROR, "no v4l2 capture context's buffers\n");
|
||||||
@ -202,20 +204,21 @@ error:
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int ff_v4l2_m2m_codec_reinit(V4L2m2mContext* s)
|
int ff_v4l2_m2m_codec_reinit(V4L2m2mContext* s)
|
||||||
{
|
{
|
||||||
|
void *log_ctx = s->priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
av_log(s->avctx, AV_LOG_DEBUG, "reinit context\n");
|
av_log(log_ctx, AV_LOG_DEBUG, "reinit context\n");
|
||||||
|
|
||||||
/* 1. streamoff */
|
/* 1. streamoff */
|
||||||
ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF);
|
ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF);
|
||||||
if (ret)
|
if (ret)
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "capture VIDIOC_STREAMOFF\n");
|
av_log(log_ctx, AV_LOG_ERROR, "capture VIDIOC_STREAMOFF\n");
|
||||||
|
|
||||||
/* 2. unmap the capture buffers (v4l2 and ffmpeg):
|
/* 2. unmap the capture buffers (v4l2 and ffmpeg):
|
||||||
* we must wait for all references to be released before being allowed
|
* we must wait for all references to be released before being allowed
|
||||||
* to queue new buffers.
|
* to queue new buffers.
|
||||||
*/
|
*/
|
||||||
av_log(s->avctx, AV_LOG_DEBUG, "waiting for user to release AVBufferRefs\n");
|
av_log(log_ctx, AV_LOG_DEBUG, "waiting for user to release AVBufferRefs\n");
|
||||||
if (atomic_load(&s->refcount))
|
if (atomic_load(&s->refcount))
|
||||||
while(sem_wait(&s->refsync) == -1 && errno == EINTR);
|
while(sem_wait(&s->refsync) == -1 && errno == EINTR);
|
||||||
|
|
||||||
@ -224,14 +227,14 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mContext* s)
|
|||||||
/* 3. get the new capture format */
|
/* 3. get the new capture format */
|
||||||
ret = ff_v4l2_context_get_format(&s->capture, 0);
|
ret = ff_v4l2_context_get_format(&s->capture, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "query the new capture format\n");
|
av_log(log_ctx, AV_LOG_ERROR, "query the new capture format\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4. set the capture format */
|
/* 4. set the capture format */
|
||||||
ret = ff_v4l2_context_set_format(&s->capture);
|
ret = ff_v4l2_context_set_format(&s->capture);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "setting capture format\n");
|
av_log(log_ctx, AV_LOG_ERROR, "setting capture format\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +307,7 @@ int ff_v4l2_m2m_codec_full_reinit(V4L2m2mContext *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* decoder's buffers need to be updated at a later stage */
|
/* decoder's buffers need to be updated at a later stage */
|
||||||
if (!av_codec_is_decoder(s->avctx->codec)) {
|
if (!s->avctx || !av_codec_is_decoder(s->avctx->codec)) {
|
||||||
ret = ff_v4l2_context_init(&s->capture);
|
ret = ff_v4l2_context_init(&s->capture);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
av_log(log_ctx, AV_LOG_ERROR, "no v4l2 capture context's buffers\n");
|
av_log(log_ctx, AV_LOG_ERROR, "no v4l2 capture context's buffers\n");
|
||||||
@ -330,19 +333,18 @@ static void v4l2_m2m_destroy_context(void *opaque, uint8_t *context)
|
|||||||
av_free(s);
|
av_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ff_v4l2_m2m_codec_end(AVCodecContext *avctx)
|
int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv)
|
||||||
{
|
{
|
||||||
V4L2m2mPriv *priv = avctx->priv_data;
|
|
||||||
V4L2m2mContext* s = priv->context;
|
V4L2m2mContext* s = priv->context;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF);
|
ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF);
|
||||||
if (ret)
|
if (ret)
|
||||||
av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name);
|
av_log(priv, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name);
|
||||||
|
|
||||||
ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF);
|
ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF);
|
||||||
if (ret)
|
if (ret)
|
||||||
av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name);
|
av_log(priv, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name);
|
||||||
|
|
||||||
ff_v4l2_context_release(&s->output);
|
ff_v4l2_context_release(&s->output);
|
||||||
|
|
||||||
@ -352,15 +354,14 @@ int ff_v4l2_m2m_codec_end(AVCodecContext *avctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ff_v4l2_m2m_codec_init(AVCodecContext *avctx)
|
int ff_v4l2_m2m_codec_init(V4L2m2mPriv *priv)
|
||||||
{
|
{
|
||||||
int ret = AVERROR(EINVAL);
|
int ret = AVERROR(EINVAL);
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
char node[PATH_MAX];
|
char node[PATH_MAX];
|
||||||
DIR *dirp;
|
DIR *dirp;
|
||||||
|
|
||||||
V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context;
|
V4L2m2mContext *s = priv->context;
|
||||||
s->avctx = avctx;
|
|
||||||
|
|
||||||
dirp = opendir("/dev");
|
dirp = opendir("/dev");
|
||||||
if (!dirp)
|
if (!dirp)
|
||||||
@ -372,7 +373,7 @@ int ff_v4l2_m2m_codec_init(AVCodecContext *avctx)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
snprintf(node, sizeof(node), "/dev/%s", entry->d_name);
|
snprintf(node, sizeof(node), "/dev/%s", entry->d_name);
|
||||||
av_log(s->avctx, AV_LOG_DEBUG, "probing device %s\n", node);
|
av_log(priv, AV_LOG_DEBUG, "probing device %s\n", node);
|
||||||
strncpy(s->devname, node, strlen(node) + 1);
|
strncpy(s->devname, node, strlen(node) + 1);
|
||||||
ret = v4l2_probe_driver(s);
|
ret = v4l2_probe_driver(s);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
@ -382,21 +383,19 @@ int ff_v4l2_m2m_codec_init(AVCodecContext *avctx)
|
|||||||
closedir(dirp);
|
closedir(dirp);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "Could not find a valid device\n");
|
av_log(priv, AV_LOG_ERROR, "Could not find a valid device\n");
|
||||||
memset(s->devname, 0, sizeof(s->devname));
|
memset(s->devname, 0, sizeof(s->devname));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
av_log(s->avctx, AV_LOG_INFO, "Using device %s\n", node);
|
av_log(priv, AV_LOG_INFO, "Using device %s\n", node);
|
||||||
|
|
||||||
return v4l2_configure_contexts(s);
|
return v4l2_configure_contexts(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ff_v4l2_m2m_create_context(AVCodecContext *avctx, V4L2m2mContext **s)
|
int ff_v4l2_m2m_create_context(V4L2m2mPriv *priv, V4L2m2mContext **s)
|
||||||
{
|
{
|
||||||
V4L2m2mPriv *priv = avctx->priv_data;
|
|
||||||
|
|
||||||
*s = av_mallocz(sizeof(V4L2m2mContext));
|
*s = av_mallocz(sizeof(V4L2m2mContext));
|
||||||
if (!*s)
|
if (!*s)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
@ -410,6 +409,7 @@ int ff_v4l2_m2m_create_context(AVCodecContext *avctx, V4L2m2mContext **s)
|
|||||||
|
|
||||||
/* assign the context */
|
/* assign the context */
|
||||||
priv->context = *s;
|
priv->context = *s;
|
||||||
|
(*s)->priv = priv;
|
||||||
|
|
||||||
/* populate it */
|
/* populate it */
|
||||||
priv->context->capture.num_buffers = priv->num_capture_buffers;
|
priv->context->capture.num_buffers = priv->num_capture_buffers;
|
||||||
|
@ -59,10 +59,12 @@ typedef struct V4L2m2mContext {
|
|||||||
|
|
||||||
/* Reference to self; only valid while codec is active. */
|
/* Reference to self; only valid while codec is active. */
|
||||||
AVBufferRef *self_ref;
|
AVBufferRef *self_ref;
|
||||||
|
|
||||||
|
/* reference back to V4L2m2mPriv */
|
||||||
|
void *priv;
|
||||||
} V4L2m2mContext;
|
} V4L2m2mContext;
|
||||||
|
|
||||||
typedef struct V4L2m2mPriv
|
typedef struct V4L2m2mPriv {
|
||||||
{
|
|
||||||
AVClass *class;
|
AVClass *class;
|
||||||
|
|
||||||
V4L2m2mContext *context;
|
V4L2m2mContext *context;
|
||||||
@ -75,33 +77,33 @@ typedef struct V4L2m2mPriv
|
|||||||
/**
|
/**
|
||||||
* Allocate a new context and references for a V4L2 M2M instance.
|
* Allocate a new context and references for a V4L2 M2M instance.
|
||||||
*
|
*
|
||||||
* @param[in] ctx The AVCodecContext instantiated by the encoder/decoder.
|
* @param[in] ctx The V4L2m2mPriv instantiated by the encoder/decoder.
|
||||||
* @param[out] ctx The V4L2m2mContext.
|
* @param[out] ctx The V4L2m2mContext.
|
||||||
*
|
*
|
||||||
* @returns 0 in success, a negative error code otherwise.
|
* @returns 0 in success, a negative error code otherwise.
|
||||||
*/
|
*/
|
||||||
int ff_v4l2_m2m_create_context(AVCodecContext *avctx, V4L2m2mContext **s);
|
int ff_v4l2_m2m_create_context(V4L2m2mPriv *priv, V4L2m2mContext **s);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Probes the video nodes looking for the required codec capabilities.
|
* Probes the video nodes looking for the required codec capabilities.
|
||||||
*
|
*
|
||||||
* @param[in] ctx The AVCodecContext instantiated by the encoder/decoder.
|
* @param[in] ctx The V4L2m2mPriv instantiated by the encoder/decoder.
|
||||||
*
|
*
|
||||||
* @returns 0 if a driver is found, a negative number otherwise.
|
* @returns 0 if a driver is found, a negative number otherwise.
|
||||||
*/
|
*/
|
||||||
int ff_v4l2_m2m_codec_init(AVCodecContext *avctx);
|
int ff_v4l2_m2m_codec_init(V4L2m2mPriv *priv);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases all the codec resources if all AVBufferRefs have been returned to the
|
* Releases all the codec resources if all AVBufferRefs have been returned to the
|
||||||
* ctx. Otherwise keep the driver open.
|
* ctx. Otherwise keep the driver open.
|
||||||
*
|
*
|
||||||
* @param[in] The AVCodecContext instantiated by the encoder/decoder.
|
* @param[in] The V4L2m2mPriv instantiated by the encoder/decoder.
|
||||||
*
|
*
|
||||||
* @returns 0
|
* @returns 0
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int ff_v4l2_m2m_codec_end(AVCodecContext *avctx);
|
int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reinitializes the V4L2m2mContext when the driver cannot continue processing
|
* Reinitializes the V4L2m2mContext when the driver cannot continue processing
|
||||||
|
@ -169,9 +169,10 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx)
|
|||||||
{
|
{
|
||||||
V4L2Context *capture, *output;
|
V4L2Context *capture, *output;
|
||||||
V4L2m2mContext *s;
|
V4L2m2mContext *s;
|
||||||
|
V4L2m2mPriv *priv = avctx->priv_data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ff_v4l2_m2m_create_context(avctx, &s);
|
ret = ff_v4l2_m2m_create_context(priv, &s);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -191,19 +192,24 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx)
|
|||||||
capture->av_codec_id = AV_CODEC_ID_RAWVIDEO;
|
capture->av_codec_id = AV_CODEC_ID_RAWVIDEO;
|
||||||
capture->av_pix_fmt = avctx->pix_fmt;
|
capture->av_pix_fmt = avctx->pix_fmt;
|
||||||
|
|
||||||
ret = ff_v4l2_m2m_codec_init(avctx);
|
ret = ff_v4l2_m2m_codec_init(priv);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
V4L2m2mPriv *priv = avctx->priv_data;
|
|
||||||
av_log(avctx, AV_LOG_ERROR, "can't configure decoder\n");
|
av_log(avctx, AV_LOG_ERROR, "can't configure decoder\n");
|
||||||
s->self_ref = NULL;
|
s->self_ref = NULL;
|
||||||
av_buffer_unref(&priv->context_ref);
|
av_buffer_unref(&priv->context_ref);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
s->avctx = avctx;
|
||||||
|
|
||||||
return v4l2_prepare_decoder(s);
|
return v4l2_prepare_decoder(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static av_cold int v4l2_decode_close(AVCodecContext *avctx)
|
||||||
|
{
|
||||||
|
return ff_v4l2_m2m_codec_end(avctx->priv_data);
|
||||||
|
}
|
||||||
|
|
||||||
#define OFFSET(x) offsetof(V4L2m2mPriv, x)
|
#define OFFSET(x) offsetof(V4L2m2mPriv, x)
|
||||||
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
|
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
|
||||||
|
|
||||||
@ -231,7 +237,7 @@ AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \
|
|||||||
.priv_class = &v4l2_m2m_ ## NAME ## _dec_class,\
|
.priv_class = &v4l2_m2m_ ## NAME ## _dec_class,\
|
||||||
.init = v4l2_decode_init,\
|
.init = v4l2_decode_init,\
|
||||||
.receive_frame = v4l2_receive_frame,\
|
.receive_frame = v4l2_receive_frame,\
|
||||||
.close = ff_v4l2_m2m_codec_end,\
|
.close = v4l2_decode_close,\
|
||||||
.bsfs = bsf_name, \
|
.bsfs = bsf_name, \
|
||||||
.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | \
|
.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | \
|
||||||
AV_CODEC_CAP_AVOID_PROBING, \
|
AV_CODEC_CAP_AVOID_PROBING, \
|
||||||
|
@ -285,9 +285,10 @@ static av_cold int v4l2_encode_init(AVCodecContext *avctx)
|
|||||||
{
|
{
|
||||||
V4L2Context *capture, *output;
|
V4L2Context *capture, *output;
|
||||||
V4L2m2mContext *s;
|
V4L2m2mContext *s;
|
||||||
|
V4L2m2mPriv *priv = avctx->priv_data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ff_v4l2_m2m_create_context(avctx, &s);
|
ret = ff_v4l2_m2m_create_context(priv, &s);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -306,15 +307,21 @@ static av_cold int v4l2_encode_init(AVCodecContext *avctx)
|
|||||||
capture->av_codec_id = avctx->codec_id;
|
capture->av_codec_id = avctx->codec_id;
|
||||||
capture->av_pix_fmt = AV_PIX_FMT_NONE;
|
capture->av_pix_fmt = AV_PIX_FMT_NONE;
|
||||||
|
|
||||||
ret = ff_v4l2_m2m_codec_init(avctx);
|
ret = ff_v4l2_m2m_codec_init(priv);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "can't configure encoder\n");
|
av_log(avctx, AV_LOG_ERROR, "can't configure encoder\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
s->avctx = avctx;
|
||||||
|
|
||||||
return v4l2_prepare_encoder(s);
|
return v4l2_prepare_encoder(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static av_cold int v4l2_encode_close(AVCodecContext *avctx)
|
||||||
|
{
|
||||||
|
return ff_v4l2_m2m_codec_end(avctx->priv_data);
|
||||||
|
}
|
||||||
|
|
||||||
#define OFFSET(x) offsetof(V4L2m2mPriv, x)
|
#define OFFSET(x) offsetof(V4L2m2mPriv, x)
|
||||||
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
||||||
|
|
||||||
@ -343,7 +350,7 @@ AVCodec ff_ ## NAME ## _v4l2m2m_encoder = { \
|
|||||||
.init = v4l2_encode_init,\
|
.init = v4l2_encode_init,\
|
||||||
.send_frame = v4l2_send_frame,\
|
.send_frame = v4l2_send_frame,\
|
||||||
.receive_packet = v4l2_receive_packet,\
|
.receive_packet = v4l2_receive_packet,\
|
||||||
.close = ff_v4l2_m2m_codec_end,\
|
.close = v4l2_encode_close,\
|
||||||
.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \
|
.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \
|
||||||
.wrapper_name = "v4l2m2m", \
|
.wrapper_name = "v4l2m2m", \
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user