X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Flibdavs2.c;h=218f3ec2396baa6ed2a203296e2787a792558dbf;hb=f12e662a3d3f489eec887b5f2ab20a550caed9cf;hp=70aae3e5eb02884df732c58e34bdf0a5cd638ca9;hpb=ef71ef5f30ddf1cd61e46628a04608892caf76d2;p=ffmpeg diff --git a/libavcodec/libdavs2.c b/libavcodec/libdavs2.c index 70aae3e5eb0..218f3ec2396 100644 --- a/libavcodec/libdavs2.c +++ b/libavcodec/libdavs2.c @@ -22,13 +22,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/avassert.h" -#include "libavutil/common.h" -#include "libavutil/avutil.h" #include "avcodec.h" -#include "libavutil/imgutils.h" -#include "internal.h" - #include "davs2.h" typedef struct DAVS2Context { @@ -38,8 +32,6 @@ typedef struct DAVS2Context { davs2_param_t param; // decoding parameters davs2_packet_t packet; // input bitstream - int decoded_frames; - davs2_picture_t out_frame; // output data, frame data davs2_seq_info_t headerset; // output data, sequence header @@ -48,22 +40,25 @@ typedef struct DAVS2Context { static av_cold int davs2_init(AVCodecContext *avctx) { DAVS2Context *cad = avctx->priv_data; + int cpu_flags = av_get_cpu_flags(); /* init the decoder */ cad->param.threads = avctx->thread_count; cad->param.info_level = 0; + cad->param.disable_avx = !(cpu_flags & AV_CPU_FLAG_AVX && + cpu_flags & AV_CPU_FLAG_AVX2); cad->decoder = davs2_decoder_open(&cad->param); if (!cad->decoder) { av_log(avctx, AV_LOG_ERROR, "decoder created error."); - return AVERROR(EINVAL); + return AVERROR_EXTERNAL; } av_log(avctx, AV_LOG_VERBOSE, "decoder created. %p\n", cad->decoder); return 0; } -static int davs2_dump_frames(AVCodecContext *avctx, davs2_picture_t *pic, +static int davs2_dump_frames(AVCodecContext *avctx, davs2_picture_t *pic, int *got_frame, davs2_seq_info_t *headerset, int ret_type, AVFrame *frame) { DAVS2Context *cad = avctx->priv_data; @@ -71,8 +66,10 @@ static int davs2_dump_frames(AVCodecContext *avctx, davs2_picture_t *pic, int plane = 0; int line = 0; - if (!headerset) + if (!headerset) { + *got_frame = 0; return 0; + } if (!pic || ret_type == DAVS2_GOT_HEADER) { avctx->width = headerset->width; @@ -81,20 +78,41 @@ static int davs2_dump_frames(AVCodecContext *avctx, davs2_picture_t *pic, AV_PIX_FMT_YUV420P10 : AV_PIX_FMT_YUV420P; avctx->framerate = av_d2q(headerset->frame_rate,4096); + *got_frame = 0; return 0; } + switch (pic->type) { + case DAVS2_PIC_I: + case DAVS2_PIC_G: + frame->pict_type = AV_PICTURE_TYPE_I; + break; + case DAVS2_PIC_P: + case DAVS2_PIC_S: + frame->pict_type = AV_PICTURE_TYPE_P; + break; + case DAVS2_PIC_B: + frame->pict_type = AV_PICTURE_TYPE_B; + break; + case DAVS2_PIC_F: + frame->pict_type = AV_PICTURE_TYPE_S; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Decoder error: unknown frame type\n"); + return AVERROR_EXTERNAL; + } + for (plane = 0; plane < 3; ++plane) { int size_line = pic->widths[plane] * bytes_per_sample; frame->buf[plane] = av_buffer_alloc(size_line * pic->lines[plane]); if (!frame->buf[plane]){ - av_log(avctx, AV_LOG_ERROR, "dump error: alloc failed.\n"); - return AVERROR(EINVAL); + av_log(avctx, AV_LOG_ERROR, "Decoder error: allocation failure, can't dump frames.\n"); + return AVERROR(ENOMEM); } frame->data[plane] = frame->buf[plane]->data; - frame->linesize[plane] = pic->widths[plane]; + frame->linesize[plane] = size_line; for (line = 0; line < pic->lines[plane]; ++line) memcpy(frame->data[plane] + line * size_line, @@ -105,11 +123,42 @@ static int davs2_dump_frames(AVCodecContext *avctx, davs2_picture_t *pic, frame->width = cad->headerset.width; frame->height = cad->headerset.height; frame->pts = cad->out_frame.pts; - frame->pict_type = pic->type; frame->format = avctx->pix_fmt; - cad->decoded_frames++; - return 1; + *got_frame = 1; + return 0; +} + +static void davs2_flush(AVCodecContext *avctx) +{ + DAVS2Context *cad = avctx->priv_data; + int ret = DAVS2_GOT_FRAME; + + while (ret == DAVS2_GOT_FRAME) { + ret = davs2_decoder_flush(cad->decoder, &cad->headerset, &cad->out_frame); + davs2_decoder_frame_unref(cad->decoder, &cad->out_frame); + } + + if (ret == DAVS2_ERROR) { + av_log(avctx, AV_LOG_WARNING, "Decoder flushing failed.\n"); + } +} + +static int send_delayed_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame) +{ + DAVS2Context *cad = avctx->priv_data; + int ret = DAVS2_DEFAULT; + + ret = davs2_decoder_flush(cad->decoder, &cad->headerset, &cad->out_frame); + if (ret == DAVS2_ERROR) { + av_log(avctx, AV_LOG_ERROR, "Decoder error: can't flush delayed frame\n"); + return AVERROR_EXTERNAL; + } + if (ret == DAVS2_GOT_FRAME) { + ret = davs2_dump_frames(avctx, &cad->out_frame, got_frame, &cad->headerset, ret, frame); + davs2_decoder_frame_unref(cad->decoder, &cad->out_frame); + } + return ret; } static av_cold int davs2_end(AVCodecContext *avctx) @@ -134,8 +183,9 @@ static int davs2_decode_frame(AVCodecContext *avctx, void *data, AVFrame *frame = data; int ret = DAVS2_DEFAULT; + /* end of stream, output what is still in the buffers */ if (!buf_size) { - return 0; + return send_delayed_frame(avctx, frame, got_frame); } cad->packet.data = buf_ptr; @@ -148,17 +198,17 @@ static int davs2_decode_frame(AVCodecContext *avctx, void *data, if (ret == DAVS2_ERROR) { av_log(avctx, AV_LOG_ERROR, "Decoder error: can't read packet\n"); - return AVERROR(EINVAL); + return AVERROR_EXTERNAL; } ret = davs2_decoder_recv_frame(cad->decoder, &cad->headerset, &cad->out_frame); if (ret != DAVS2_DEFAULT) { - *got_frame = davs2_dump_frames(avctx, &cad->out_frame, &cad->headerset, ret, frame); + ret = davs2_dump_frames(avctx, &cad->out_frame, got_frame, &cad->headerset, ret, frame); davs2_decoder_frame_unref(cad->decoder, &cad->out_frame); } - return buf_size; + return ret == 0 ? buf_size : ret; } AVCodec ff_libdavs2_decoder = { @@ -170,8 +220,9 @@ AVCodec ff_libdavs2_decoder = { .init = davs2_init, .close = davs2_end, .decode = davs2_decode_frame, - .capabilities = AV_CODEC_CAP_DELAY,//AV_CODEC_CAP_DR1 | - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10, + .flush = davs2_flush, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .wrapper_name = "libdavs2", };