X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fv4l2_buffers.c;h=4b2679eb38140e85c652b4707ab3a146c59a2b0f;hb=b593abda6c642cb0c3959752dd235c2faf66837f;hp=46c9f11d7bee472bdd25676d1ccc2798a3a2ef1d;hpb=3475758a3791dc89c6e7c406f8b032f035cd7d1e;p=ffmpeg diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index 46c9f11d7be..4b2679eb381 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -35,6 +35,7 @@ #include "v4l2_m2m.h" #define USEC_PER_SEC 1000000 +static AVRational v4l2_timebase = { 1, USEC_PER_SEC }; static inline V4L2m2mContext *buf_to_m2mctx(V4L2Buffer *buf) { @@ -48,32 +49,37 @@ static inline AVCodecContext *logger(V4L2Buffer *buf) return buf_to_m2mctx(buf)->avctx; } +static inline AVRational v4l2_get_timebase(V4L2Buffer *avbuf) +{ + V4L2m2mContext *s = buf_to_m2mctx(avbuf); + + if (s->avctx->pkt_timebase.num) + return s->avctx->pkt_timebase; + return s->avctx->time_base; +} + static inline void v4l2_set_pts(V4L2Buffer *out, int64_t pts) { - V4L2m2mContext *s = buf_to_m2mctx(out); - AVRational v4l2_timebase = { 1, USEC_PER_SEC }; int64_t v4l2_pts; if (pts == AV_NOPTS_VALUE) pts = 0; /* convert pts to v4l2 timebase */ - v4l2_pts = av_rescale_q(pts, s->avctx->time_base, v4l2_timebase); + v4l2_pts = av_rescale_q(pts, v4l2_get_timebase(out), v4l2_timebase); out->buf.timestamp.tv_usec = v4l2_pts % USEC_PER_SEC; out->buf.timestamp.tv_sec = v4l2_pts / USEC_PER_SEC; } static inline int64_t v4l2_get_pts(V4L2Buffer *avbuf) { - V4L2m2mContext *s = buf_to_m2mctx(avbuf); - AVRational v4l2_timebase = { 1, USEC_PER_SEC }; int64_t v4l2_pts; /* convert pts back to encoder timebase */ v4l2_pts = (int64_t)avbuf->buf.timestamp.tv_sec * USEC_PER_SEC + avbuf->buf.timestamp.tv_usec; - return av_rescale_q(v4l2_pts, v4l2_timebase, s->avctx->time_base); + return av_rescale_q(v4l2_pts, v4l2_timebase, v4l2_get_timebase(avbuf)); } static enum AVColorPrimaries v4l2_get_color_primaries(V4L2Buffer *buf) @@ -216,7 +222,7 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused) if (!atomic_load(&s->refcount)) sem_post(&s->refsync); } else { - if (s->draining) { + if (s->draining && V4L2_TYPE_IS_OUTPUT(avbuf->context->type)) { /* no need to queue more buffers to the driver */ avbuf->status = V4L2BUF_AVAILABLE; } @@ -268,7 +274,7 @@ static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf) return ret; } -static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, int offset, AVBufferRef* bref) +static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, int offset) { unsigned int bytesused, length; @@ -345,10 +351,18 @@ static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) switch (pixel_format) { case V4L2_PIX_FMT_YUV420M: case V4L2_PIX_FMT_YVU420M: +#ifdef V4L2_PIX_FMT_YUV422M case V4L2_PIX_FMT_YUV422M: +#endif +#ifdef V4L2_PIX_FMT_YVU422M case V4L2_PIX_FMT_YVU422M: +#endif +#ifdef V4L2_PIX_FMT_YUV444M case V4L2_PIX_FMT_YUV444M: +#endif +#ifdef V4L2_PIX_FMT_YVU444M case V4L2_PIX_FMT_YVU444M: +#endif case V4L2_PIX_FMT_NV12M: case V4L2_PIX_FMT_NV21M: case V4L2_PIX_FMT_NV12MT_16X16: @@ -372,7 +386,7 @@ static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) h = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); } size = frame->linesize[i] * h; - ret = v4l2_bufref_to_buf(out, 0, frame->data[i], size, offset, frame->buf[i]); + ret = v4l2_bufref_to_buf(out, 0, frame->data[i], size, offset); if (ret) return ret; offset += size; @@ -381,7 +395,7 @@ static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) } for (i = 0; i < out->num_planes; i++) { - ret = v4l2_bufref_to_buf(out, i, frame->buf[i]->data, frame->buf[i]->size, 0, frame->buf[i]); + ret = v4l2_bufref_to_buf(out, i, frame->buf[i]->data, frame->buf[i]->size, 0); if (ret) return ret; } @@ -422,9 +436,10 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) frame->pts = v4l2_get_pts(avbuf); frame->pkt_dts = AV_NOPTS_VALUE; - /* these two values are updated also during re-init in v4l2_process_driver_event */ + /* these values are updated also during re-init in v4l2_process_driver_event */ frame->height = avbuf->context->height; frame->width = avbuf->context->width; + frame->sample_aspect_ratio = avbuf->context->sample_aspect_ratio; /* 3. report errors upstream */ if (avbuf->buf.flags & V4L2_BUF_FLAG_ERROR) { @@ -464,7 +479,7 @@ int ff_v4l2_buffer_avpkt_to_buf(const AVPacket *pkt, V4L2Buffer *out) { int ret; - ret = v4l2_bufref_to_buf(out, 0, pkt->data, pkt->size, 0, pkt->buf); + ret = v4l2_bufref_to_buf(out, 0, pkt->data, pkt->size, 0); if (ret) return ret; @@ -496,11 +511,9 @@ int ff_v4l2_buffer_initialize(V4L2Buffer* avbuf, int index) if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { avbuf->num_planes = 0; - for (;;) { - /* in MP, the V4L2 API states that buf.length means num_planes */ - if (avbuf->num_planes >= avbuf->buf.length) - break; - if (avbuf->buf.m.planes[avbuf->num_planes].length) + /* in MP, the V4L2 API states that buf.length means num_planes */ + for (i = 0; i < avbuf->buf.length; i++) { + if (avbuf->buf.m.planes[i].length) avbuf->num_planes++; } } else