On 2014-04-17 20:38:27 +0200, Anton Khirnov wrote:
>
> On Tue, 25 Mar 2014 11:13:37 +0100, Janne Grunau <[email protected]>
> wrote:
> > On 2014-03-24 21:20:27 +0100, Luca Barbato wrote:
> > > On 24/03/14 20:26, wm4 wrote:
> > > > In practice, it's called when the decoder is flushed, i.e. on seeking.
> > > > And yes, this is a bit of a bother. Freeing all hardware surfaces and
> > > > reallocating them etc. makes seeking quite a bit slower this way.
> > >
> > > I'm not sure how to make it more optimal, if you have ideas I'm all hears.
> >
> > I don't think it necessary to call get_format() unconditionally after
> > seeking. Fixing it in h264.c might be not so nice though.
> >
> > I guess h264.c is not the only decoder which needs fixing. I'll look
> > into it.
> >
>
> Any progress?
Not fully convinced from patch below. Without changes in the stream
get_format will be only called once. That might break applications
using the codec context from avformat_find_stream_info.
One the plus side it's non-ugly and adding support for all other codecs
is a triviality.
Janne
---8<---
The most compelling place to initialize the hardware of AVHWAccel-backed
decoders is the get_format callback. To avoid unneeded reinitializations
ff_get_format() calls get_format() only if the previously returned pixel
format is not in the new pixel format list.
---
libavcodec/h264_slice.c | 10 +++++-----
libavcodec/internal.h | 15 +++++++++++++++
libavcodec/utils.c | 20 ++++++++++++++++++++
3 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 897c8eb..683dead 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -1011,11 +1011,11 @@ static enum AVPixelFormat get_pixel_format(H264Context
*h)
return h->avctx->color_range == AVCOL_RANGE_JPEG ?
AV_PIX_FMT_YUVJ422P
:
AV_PIX_FMT_YUV422P;
} else {
- return h->avctx->get_format(h->avctx, h->avctx->codec->pix_fmts ?
- h->avctx->codec->pix_fmts :
- h->avctx->color_range ==
AVCOL_RANGE_JPEG ?
- h264_hwaccel_pixfmt_list_jpeg_420 :
- h264_hwaccel_pixfmt_list_420);
+ return ff_get_format(h->avctx, h->avctx->codec->pix_fmts ?
+ h->avctx->codec->pix_fmts :
+ h->avctx->color_range == AVCOL_RANGE_JPEG ?
+ h264_hwaccel_pixfmt_list_jpeg_420 :
+ h264_hwaccel_pixfmt_list_420);
}
break;
default:
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 268a758..10f3530 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -95,6 +95,13 @@ typedef struct AVCodecInternal {
* packet into every function.
*/
AVPacket *pkt;
+
+ /**
+ * AVPixelFormat returned by the last AVCodecContext.get_format() call.
+ * Used to avoid get_format() calls after flush/seeking if the pixel format
+ * has not changed.
+ */
+ enum AVPixelFormat current_pix_fmt;
} AVCodecInternal;
struct AVCodecDefault {
@@ -170,6 +177,14 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame,
int flags);
*/
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame);
+/**
+ * Let the user choose the preferred pixel format. This is a wrapper around
+ * AVCodecContext.get_format() and should be used instead calling get_format()
+ * directly when the codec supports AVHWAccels.
+ */
+enum AVPixelFormat ff_get_format(struct AVCodecContext *s,
+ const enum AVPixelFormat *fmt);
+
const uint8_t *avpriv_find_start_code(const uint8_t *restrict p,
const uint8_t *end,
uint32_t *restrict state);
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index d9832e2..203ea8e 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -863,6 +863,25 @@ enum AVPixelFormat avcodec_default_get_format(struct
AVCodecContext *s, const en
return fmt[0];
}
+enum AVPixelFormat ff_get_format(struct AVCodecContext *s,
+ const enum AVPixelFormat *fmt)
+{
+ unsigned i = 0;
+
+ if (s->internal->current_pix_fmt != AV_PIX_FMT_NONE &&
+ is_hwaccel_pix_fmt(s->internal->current_pix_fmt)) {
+ while (fmt[i] != AV_PIX_FMT_NONE) {
+ if (fmt[i] == s->internal->current_pix_fmt)
+ return s->internal->current_pix_fmt;
+ i++;
+ }
+ }
+
+ s->internal->current_pix_fmt = s->get_format(s, fmt);
+
+ return s->internal->current_pix_fmt;
+}
+
#if FF_API_AVFRAME_LAVC
void avcodec_get_frame_defaults(AVFrame *frame)
{
@@ -942,6 +961,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext
*avctx, const AVCodec *code
ret = AVERROR(ENOMEM);
goto end;
}
+ avctx->internal->current_pix_fmt = AV_PIX_FMT_NONE;
avctx->internal->pool = av_mallocz(sizeof(*avctx->internal->pool));
if (!avctx->internal->pool) {
--
1.9.2
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel