]> git.sesse.net Git - ffmpeg/blob - libavcodec/bsf.c
Merge commit '33d18982fa03feb061c8f744a4f0a9175c1f63ab'
[ffmpeg] / libavcodec / bsf.c
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #include <string.h>
20
21 #include "libavutil/log.h"
22 #include "libavutil/mem.h"
23 #include "libavutil/opt.h"
24
25 #include "avcodec.h"
26 #include "bsf.h"
27
28 struct AVBSFInternal {
29     AVPacket *buffer_pkt;
30     int eof;
31 };
32
33 void av_bsf_free(AVBSFContext **pctx)
34 {
35     AVBSFContext *ctx;
36
37     if (!pctx || !*pctx)
38         return;
39     ctx = *pctx;
40
41     if (ctx->filter->close)
42         ctx->filter->close(ctx);
43     if (ctx->filter->priv_class && ctx->priv_data)
44         av_opt_free(ctx->priv_data);
45
46     av_opt_free(ctx);
47
48     av_packet_free(&ctx->internal->buffer_pkt);
49     av_freep(&ctx->internal);
50     av_freep(&ctx->priv_data);
51
52     avcodec_parameters_free(&ctx->par_in);
53     avcodec_parameters_free(&ctx->par_out);
54
55     av_freep(pctx);
56 }
57
58 static void *bsf_child_next(void *obj, void *prev)
59 {
60     AVBSFContext *ctx = obj;
61     if (!prev && ctx->filter->priv_class)
62         return ctx->priv_data;
63     return NULL;
64 }
65
66 static const AVClass bsf_class = {
67     .class_name       = "AVBSFContext",
68     .item_name        = av_default_item_name,
69     .version          = LIBAVUTIL_VERSION_INT,
70     .child_next       = bsf_child_next,
71     .child_class_next = ff_bsf_child_class_next,
72 };
73
74 const AVClass *av_bsf_get_class(void)
75 {
76     return &bsf_class;
77 }
78
79 int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx)
80 {
81     AVBSFContext *ctx;
82     int ret;
83
84     ctx = av_mallocz(sizeof(*ctx));
85     if (!ctx)
86         return AVERROR(ENOMEM);
87
88     ctx->av_class = &bsf_class;
89     ctx->filter   = filter;
90
91     ctx->par_in  = avcodec_parameters_alloc();
92     ctx->par_out = avcodec_parameters_alloc();
93     if (!ctx->par_in || !ctx->par_out) {
94         ret = AVERROR(ENOMEM);
95         goto fail;
96     }
97
98     ctx->internal = av_mallocz(sizeof(*ctx->internal));
99     if (!ctx->internal) {
100         ret = AVERROR(ENOMEM);
101         goto fail;
102     }
103
104     ctx->internal->buffer_pkt = av_packet_alloc();
105     if (!ctx->internal->buffer_pkt) {
106         ret = AVERROR(ENOMEM);
107         goto fail;
108     }
109
110     av_opt_set_defaults(ctx);
111
112     /* allocate priv data and init private options */
113     if (filter->priv_data_size) {
114         ctx->priv_data = av_mallocz(filter->priv_data_size);
115         if (!ctx->priv_data) {
116             ret = AVERROR(ENOMEM);
117             goto fail;
118         }
119         if (filter->priv_class) {
120             *(const AVClass **)ctx->priv_data = filter->priv_class;
121             av_opt_set_defaults(ctx->priv_data);
122         }
123     }
124
125     *pctx = ctx;
126     return 0;
127 fail:
128     av_bsf_free(&ctx);
129     return ret;
130 }
131
132 int av_bsf_init(AVBSFContext *ctx)
133 {
134     int ret, i;
135
136     /* check that the codec is supported */
137     if (ctx->filter->codec_ids) {
138         for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++)
139             if (ctx->par_in->codec_id == ctx->filter->codec_ids[i])
140                 break;
141         if (ctx->filter->codec_ids[i] == AV_CODEC_ID_NONE) {
142             const AVCodecDescriptor *desc = avcodec_descriptor_get(ctx->par_in->codec_id);
143             av_log(ctx, AV_LOG_ERROR, "Codec '%s' (%d) is not supported by the "
144                    "bitstream filter '%s'. Supported codecs are: ",
145                    desc ? desc->name : "unknown", ctx->par_in->codec_id, ctx->filter->name);
146             for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++) {
147                 desc = avcodec_descriptor_get(ctx->filter->codec_ids[i]);
148                 av_log(ctx, AV_LOG_ERROR, "%s (%d) ",
149                        desc ? desc->name : "unknown", ctx->filter->codec_ids[i]);
150             }
151             av_log(ctx, AV_LOG_ERROR, "\n");
152             return AVERROR(EINVAL);
153         }
154     }
155
156     /* initialize output parameters to be the same as input
157      * init below might overwrite that */
158     ret = avcodec_parameters_copy(ctx->par_out, ctx->par_in);
159     if (ret < 0)
160         return ret;
161
162     ctx->time_base_out = ctx->time_base_in;
163
164     if (ctx->filter->init) {
165         ret = ctx->filter->init(ctx);
166         if (ret < 0)
167             return ret;
168     }
169
170     return 0;
171 }
172
173 int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt)
174 {
175     if (!pkt || !pkt->data) {
176         ctx->internal->eof = 1;
177         return 0;
178     }
179
180     if (ctx->internal->eof) {
181         av_log(ctx, AV_LOG_ERROR, "A non-NULL packet sent after an EOF.\n");
182         return AVERROR(EINVAL);
183     }
184
185     if (ctx->internal->buffer_pkt->data ||
186         ctx->internal->buffer_pkt->side_data_elems)
187         return AVERROR(EAGAIN);
188
189     av_packet_move_ref(ctx->internal->buffer_pkt, pkt);
190
191     return 0;
192 }
193
194 int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt)
195 {
196     return ctx->filter->filter(ctx, pkt);
197 }
198
199 int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt)
200 {
201     AVBSFInternal *in = ctx->internal;
202     AVPacket *tmp_pkt;
203
204     if (in->eof)
205         return AVERROR_EOF;
206
207     if (!ctx->internal->buffer_pkt->data &&
208         !ctx->internal->buffer_pkt->side_data_elems)
209         return AVERROR(EAGAIN);
210
211     tmp_pkt = av_packet_alloc();
212     if (!tmp_pkt)
213         return AVERROR(ENOMEM);
214
215     *pkt = ctx->internal->buffer_pkt;
216     ctx->internal->buffer_pkt = tmp_pkt;
217
218     return 0;
219 }