avcodec/dump_extradata_bsf: don't allocate a new AVPacket per filtered packet
[ffmpeg.git] / libavcodec / libdavs2.c
1 /*
2  * AVS2 decoding using the davs2 library
3  *
4  * Copyright (C) 2018 Yiqun Xu, <yiqun.xu@vipl.ict.ac.cn>
5  *                    Falei Luo, <falei.luo@gmail.com>
6  *                    Huiwen Ren, <hwrenx@gmail.com>
7  *
8  * This file is part of FFmpeg.
9  *
10  * FFmpeg is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * FFmpeg is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with FFmpeg; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24
25 #include "libavutil/avassert.h"
26 #include "libavutil/common.h"
27 #include "libavutil/avutil.h"
28 #include "avcodec.h"
29 #include "libavutil/imgutils.h"
30 #include "internal.h"
31
32 #include "davs2.h"
33
34 typedef struct DAVS2Context {
35     void *decoder;
36
37     AVFrame *frame;
38     davs2_param_t    param;      // decoding parameters
39     davs2_packet_t   packet;     // input bitstream
40
41     int decoded_frames;
42
43     davs2_picture_t  out_frame;  // output data, frame data
44     davs2_seq_info_t headerset;  // output data, sequence header
45
46 }DAVS2Context;
47
48 static av_cold int davs2_init(AVCodecContext *avctx)
49 {
50     DAVS2Context *cad = avctx->priv_data;
51
52     /* init the decoder */
53     cad->param.threads      = avctx->thread_count;
54     cad->param.info_level   = 0;
55     cad->decoder            = davs2_decoder_open(&cad->param);
56
57     if (!cad->decoder) {
58         av_log(avctx, AV_LOG_ERROR, "decoder created error.");
59         return AVERROR(EINVAL);
60     }
61
62     av_log(avctx, AV_LOG_VERBOSE, "decoder created. %p\n", cad->decoder);
63     return 0;
64 }
65
66 static int davs2_dump_frames(AVCodecContext *avctx, davs2_picture_t *pic,
67                              davs2_seq_info_t *headerset, int ret_type, AVFrame *frame)
68 {
69     DAVS2Context *cad    = avctx->priv_data;
70     int bytes_per_sample = pic->bytes_per_sample;
71     int plane = 0;
72     int line  = 0;
73
74     if (!headerset)
75         return 0;
76
77     if (!pic || ret_type == DAVS2_GOT_HEADER) {
78         avctx->width     = headerset->width;
79         avctx->height    = headerset->height;
80         avctx->pix_fmt   = headerset->output_bit_depth == 10 ?
81                            AV_PIX_FMT_YUV420P10 : AV_PIX_FMT_YUV420P;
82
83         avctx->framerate = av_d2q(headerset->frame_rate,4096);
84         return 0;
85     }
86
87     for (plane = 0; plane < 3; ++plane) {
88         int size_line = pic->widths[plane] * bytes_per_sample;
89         frame->buf[plane]  = av_buffer_alloc(size_line * pic->lines[plane]);
90
91         if (!frame->buf[plane]){
92             av_log(avctx, AV_LOG_ERROR, "dump error: alloc failed.\n");
93             return AVERROR(EINVAL);
94         }
95
96         frame->data[plane]     = frame->buf[plane]->data;
97         frame->linesize[plane] = pic->widths[plane];
98
99         for (line = 0; line < pic->lines[plane]; ++line)
100             memcpy(frame->data[plane] + line * size_line,
101                    pic->planes[plane] + line * pic->strides[plane],
102                    pic->widths[plane] * bytes_per_sample);
103     }
104
105     frame->width     = cad->headerset.width;
106     frame->height    = cad->headerset.height;
107     frame->pts       = cad->out_frame.pts;
108     frame->pict_type = pic->type;
109     frame->format    = avctx->pix_fmt;
110
111     cad->decoded_frames++;
112     return 1;
113 }
114
115 static av_cold int davs2_end(AVCodecContext *avctx)
116 {
117     DAVS2Context *cad = avctx->priv_data;
118
119     /* close the decoder */
120     if (cad->decoder) {
121         davs2_decoder_close(cad->decoder);
122         cad->decoder = NULL;
123     }
124
125     return 0;
126 }
127
128 static int davs2_decode_frame(AVCodecContext *avctx, void *data,
129                               int *got_frame, AVPacket *avpkt)
130 {
131     DAVS2Context *cad      = avctx->priv_data;
132     int           buf_size = avpkt->size;
133     uint8_t      *buf_ptr  = avpkt->data;
134     AVFrame      *frame    = data;
135     int           ret      = DAVS2_DEFAULT;
136
137     if (!buf_size) {
138         return 0;
139     }
140
141     cad->packet.data = buf_ptr;
142     cad->packet.len  = buf_size;
143     cad->packet.pts  = avpkt->pts;
144     cad->packet.dts  = avpkt->dts;
145
146     ret = davs2_decoder_send_packet(cad->decoder, &cad->packet);
147
148
149     if (ret == DAVS2_ERROR) {
150         av_log(avctx, AV_LOG_ERROR, "Decoder error: can't read packet\n");
151         return AVERROR(EINVAL);
152     }
153
154     ret = davs2_decoder_recv_frame(cad->decoder, &cad->headerset, &cad->out_frame);
155
156     if (ret != DAVS2_DEFAULT) {
157         *got_frame = davs2_dump_frames(avctx, &cad->out_frame, &cad->headerset, ret, frame);
158         davs2_decoder_frame_unref(cad->decoder, &cad->out_frame);
159     }
160
161     return buf_size;
162 }
163
164 AVCodec ff_libdavs2_decoder = {
165     .name           = "libdavs2",
166     .long_name      = NULL_IF_CONFIG_SMALL("Decoder for AVS2/IEEE 1857.4"),
167     .type           = AVMEDIA_TYPE_VIDEO,
168     .id             = AV_CODEC_ID_AVS2,
169     .priv_data_size = sizeof(DAVS2Context),
170     .init           = davs2_init,
171     .close          = davs2_end,
172     .decode         = davs2_decode_frame,
173     .capabilities   =  AV_CODEC_CAP_DELAY,//AV_CODEC_CAP_DR1 |
174     .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10,
175                                                      AV_PIX_FMT_NONE },
176     .wrapper_name   = "libdavs2",
177 };