xref: /third_party/ffmpeg/libavcodec/codec_par.c (revision cabdff1a)
1/*
2 * AVCodecParameters functions for libavcodec
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/**
22 * @file
23 * AVCodecParameters functions for libavcodec.
24 */
25
26#include <string.h>
27#include "libavutil/mem.h"
28#include "avcodec.h"
29#include "codec_par.h"
30
31static void codec_parameters_reset(AVCodecParameters *par)
32{
33    av_freep(&par->extradata);
34    av_channel_layout_uninit(&par->ch_layout);
35
36    memset(par, 0, sizeof(*par));
37
38    par->codec_type          = AVMEDIA_TYPE_UNKNOWN;
39    par->codec_id            = AV_CODEC_ID_NONE;
40    par->format              = -1;
41    par->ch_layout.order     = AV_CHANNEL_ORDER_UNSPEC;
42    par->field_order         = AV_FIELD_UNKNOWN;
43    par->color_range         = AVCOL_RANGE_UNSPECIFIED;
44    par->color_primaries     = AVCOL_PRI_UNSPECIFIED;
45    par->color_trc           = AVCOL_TRC_UNSPECIFIED;
46    par->color_space         = AVCOL_SPC_UNSPECIFIED;
47    par->chroma_location     = AVCHROMA_LOC_UNSPECIFIED;
48    par->sample_aspect_ratio = (AVRational){ 0, 1 };
49    par->profile             = FF_PROFILE_UNKNOWN;
50    par->level               = FF_LEVEL_UNKNOWN;
51}
52
53AVCodecParameters *avcodec_parameters_alloc(void)
54{
55    AVCodecParameters *par = av_mallocz(sizeof(*par));
56
57    if (!par)
58        return NULL;
59    codec_parameters_reset(par);
60    return par;
61}
62
63void avcodec_parameters_free(AVCodecParameters **ppar)
64{
65    AVCodecParameters *par = *ppar;
66
67    if (!par)
68        return;
69    codec_parameters_reset(par);
70
71    av_freep(ppar);
72}
73
74int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
75{
76    int ret;
77
78    codec_parameters_reset(dst);
79    memcpy(dst, src, sizeof(*dst));
80
81    dst->ch_layout      = (AVChannelLayout){0};
82    dst->extradata      = NULL;
83    dst->extradata_size = 0;
84    if (src->extradata) {
85        dst->extradata = av_mallocz(src->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
86        if (!dst->extradata)
87            return AVERROR(ENOMEM);
88        memcpy(dst->extradata, src->extradata, src->extradata_size);
89        dst->extradata_size = src->extradata_size;
90    }
91
92    ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout);
93    if (ret < 0)
94        return ret;
95
96    return 0;
97}
98
99int avcodec_parameters_from_context(AVCodecParameters *par,
100                                    const AVCodecContext *codec)
101{
102    int ret;
103
104    codec_parameters_reset(par);
105
106    par->codec_type = codec->codec_type;
107    par->codec_id   = codec->codec_id;
108    par->codec_tag  = codec->codec_tag;
109
110    par->bit_rate              = codec->bit_rate;
111    par->bits_per_coded_sample = codec->bits_per_coded_sample;
112    par->bits_per_raw_sample   = codec->bits_per_raw_sample;
113    par->profile               = codec->profile;
114    par->level                 = codec->level;
115
116    switch (par->codec_type) {
117    case AVMEDIA_TYPE_VIDEO:
118        par->format              = codec->pix_fmt;
119        par->width               = codec->width;
120        par->height              = codec->height;
121        par->field_order         = codec->field_order;
122        par->color_range         = codec->color_range;
123        par->color_primaries     = codec->color_primaries;
124        par->color_trc           = codec->color_trc;
125        par->color_space         = codec->colorspace;
126        par->chroma_location     = codec->chroma_sample_location;
127        par->sample_aspect_ratio = codec->sample_aspect_ratio;
128        par->video_delay         = codec->has_b_frames;
129        break;
130    case AVMEDIA_TYPE_AUDIO:
131        par->format           = codec->sample_fmt;
132#if FF_API_OLD_CHANNEL_LAYOUT
133FF_DISABLE_DEPRECATION_WARNINGS
134        // if the old/new fields are set inconsistently, prefer the old ones
135        if ((codec->channels && codec->channels != codec->ch_layout.nb_channels) ||
136            (codec->channel_layout && (codec->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
137                                       codec->ch_layout.u.mask != codec->channel_layout))) {
138            if (codec->channel_layout)
139                av_channel_layout_from_mask(&par->ch_layout, codec->channel_layout);
140            else {
141                par->ch_layout.order       = AV_CHANNEL_ORDER_UNSPEC;
142                par->ch_layout.nb_channels = codec->channels;
143            }
144FF_ENABLE_DEPRECATION_WARNINGS
145        } else {
146#endif
147        ret = av_channel_layout_copy(&par->ch_layout, &codec->ch_layout);
148        if (ret < 0)
149            return ret;
150#if FF_API_OLD_CHANNEL_LAYOUT
151FF_DISABLE_DEPRECATION_WARNINGS
152        }
153        par->channel_layout  = par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ?
154                               par->ch_layout.u.mask : 0;
155        par->channels        = par->ch_layout.nb_channels;
156FF_ENABLE_DEPRECATION_WARNINGS
157#endif
158        par->sample_rate      = codec->sample_rate;
159        par->block_align      = codec->block_align;
160        par->frame_size       = codec->frame_size;
161        par->initial_padding  = codec->initial_padding;
162        par->trailing_padding = codec->trailing_padding;
163        par->seek_preroll     = codec->seek_preroll;
164        break;
165    case AVMEDIA_TYPE_SUBTITLE:
166        par->width  = codec->width;
167        par->height = codec->height;
168        break;
169    }
170
171    if (codec->extradata) {
172        par->extradata = av_mallocz(codec->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
173        if (!par->extradata)
174            return AVERROR(ENOMEM);
175        memcpy(par->extradata, codec->extradata, codec->extradata_size);
176        par->extradata_size = codec->extradata_size;
177    }
178
179    return 0;
180}
181
182int avcodec_parameters_to_context(AVCodecContext *codec,
183                                  const AVCodecParameters *par)
184{
185    int ret;
186
187    codec->codec_type = par->codec_type;
188    codec->codec_id   = par->codec_id;
189    codec->codec_tag  = par->codec_tag;
190
191    codec->bit_rate              = par->bit_rate;
192    codec->bits_per_coded_sample = par->bits_per_coded_sample;
193    codec->bits_per_raw_sample   = par->bits_per_raw_sample;
194    codec->profile               = par->profile;
195    codec->level                 = par->level;
196
197    switch (par->codec_type) {
198    case AVMEDIA_TYPE_VIDEO:
199        codec->pix_fmt                = par->format;
200        codec->width                  = par->width;
201        codec->height                 = par->height;
202        codec->field_order            = par->field_order;
203        codec->color_range            = par->color_range;
204        codec->color_primaries        = par->color_primaries;
205        codec->color_trc              = par->color_trc;
206        codec->colorspace             = par->color_space;
207        codec->chroma_sample_location = par->chroma_location;
208        codec->sample_aspect_ratio    = par->sample_aspect_ratio;
209        codec->has_b_frames           = par->video_delay;
210        break;
211    case AVMEDIA_TYPE_AUDIO:
212        codec->sample_fmt       = par->format;
213#if FF_API_OLD_CHANNEL_LAYOUT
214FF_DISABLE_DEPRECATION_WARNINGS
215        // if the old/new fields are set inconsistently, prefer the old ones
216        if ((par->channels && par->channels != par->ch_layout.nb_channels) ||
217            (par->channel_layout && (par->ch_layout.order != AV_CHANNEL_ORDER_NATIVE ||
218                                     par->ch_layout.u.mask != par->channel_layout))) {
219            if (par->channel_layout)
220                av_channel_layout_from_mask(&codec->ch_layout, par->channel_layout);
221            else {
222                codec->ch_layout.order       = AV_CHANNEL_ORDER_UNSPEC;
223                codec->ch_layout.nb_channels = par->channels;
224            }
225FF_ENABLE_DEPRECATION_WARNINGS
226        } else {
227#endif
228        ret = av_channel_layout_copy(&codec->ch_layout, &par->ch_layout);
229        if (ret < 0)
230            return ret;
231#if FF_API_OLD_CHANNEL_LAYOUT
232FF_DISABLE_DEPRECATION_WARNINGS
233        }
234        codec->channel_layout = codec->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ?
235                                codec->ch_layout.u.mask : 0;
236        codec->channels       = codec->ch_layout.nb_channels;
237FF_ENABLE_DEPRECATION_WARNINGS
238#endif
239        codec->sample_rate      = par->sample_rate;
240        codec->block_align      = par->block_align;
241        codec->frame_size       = par->frame_size;
242        codec->delay            =
243        codec->initial_padding  = par->initial_padding;
244        codec->trailing_padding = par->trailing_padding;
245        codec->seek_preroll     = par->seek_preroll;
246        break;
247    case AVMEDIA_TYPE_SUBTITLE:
248        codec->width  = par->width;
249        codec->height = par->height;
250        break;
251    }
252
253    if (par->extradata) {
254        av_freep(&codec->extradata);
255        codec->extradata = av_mallocz(par->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
256        if (!codec->extradata)
257            return AVERROR(ENOMEM);
258        memcpy(codec->extradata, par->extradata, par->extradata_size);
259        codec->extradata_size = par->extradata_size;
260    }
261
262    return 0;
263}
264