/* * Various functions used by both muxers and demuxers * Copyright (c) 2000, 2001, 2002 Fabrice Bellard * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libavutil/avassert.h" #include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavcodec/avcodec.h" #include "libavcodec/bsf.h" #include "libavcodec/packet_internal.h" #include "avformat.h" #include "demux.h" #include "internal.h" void ff_free_stream(AVStream **pst) { AVStream *st = *pst; FFStream *const sti = ffstream(st); if (!st) return; for (int i = 0; i < st->nb_side_data; i++) av_freep(&st->side_data[i].data); av_freep(&st->side_data); if (st->attached_pic.data) av_packet_unref(&st->attached_pic); av_parser_close(sti->parser); avcodec_free_context(&sti->avctx); av_bsf_free(&sti->bsfc); av_freep(&sti->priv_pts); av_freep(&sti->index_entries); av_freep(&sti->probe_data.buf); av_bsf_free(&sti->extract_extradata.bsf); if (sti->info) { av_freep(&sti->info->duration_error); av_freep(&sti->info); } av_dict_free(&st->metadata); avcodec_parameters_free(&st->codecpar); av_freep(&st->priv_data); av_freep(pst); } void ff_remove_stream(AVFormatContext *s, AVStream *st) { av_assert0(s->nb_streams>0); av_assert0(s->streams[ s->nb_streams - 1 ] == st); ff_free_stream(&s->streams[ --s->nb_streams ]); } /* XXX: suppress the packet queue */ void ff_flush_packet_queue(AVFormatContext *s) { FFFormatContext *const si = ffformatcontext(s); avpriv_packet_list_free(&si->parse_queue); avpriv_packet_list_free(&si->packet_buffer); avpriv_packet_list_free(&si->raw_packet_buffer); si->raw_packet_buffer_size = 0; } void avformat_free_context(AVFormatContext *s) { FFFormatContext *si; if (!s) return; si = ffformatcontext(s); if (s->oformat && s->oformat->deinit && si->initialized) s->oformat->deinit(s); av_opt_free(s); if (s->iformat && s->iformat->priv_class && s->priv_data) av_opt_free(s->priv_data); if (s->oformat && s->oformat->priv_class && s->priv_data) av_opt_free(s->priv_data); for (unsigned i = 0; i < s->nb_streams; i++) ff_free_stream(&s->streams[i]); s->nb_streams = 0; for (unsigned i = 0; i < s->nb_programs; i++) { av_dict_free(&s->programs[i]->metadata); av_freep(&s->programs[i]->stream_index); av_freep(&s->programs[i]); } s->nb_programs = 0; av_freep(&s->programs); av_freep(&s->priv_data); while (s->nb_chapters--) { av_dict_free(&s->chapters[s->nb_chapters]->metadata); av_freep(&s->chapters[s->nb_chapters]); } av_freep(&s->chapters); av_dict_free(&s->metadata); av_dict_free(&si->id3v2_meta); av_packet_free(&si->pkt); av_packet_free(&si->parse_pkt); av_freep(&s->streams); ff_flush_packet_queue(s); av_freep(&s->url); av_free(s); } uint8_t *av_stream_get_side_data(const AVStream *st, enum AVPacketSideDataType type, size_t *size) { for (int i = 0; i < st->nb_side_data; i++) { if (st->side_data[i].type == type) { if (size) *size = st->side_data[i].size; return st->side_data[i].data; } } if (size) *size = 0; return NULL; } int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type, uint8_t *data, size_t size) { AVPacketSideData *sd, *tmp; for (int i = 0; i < st->nb_side_data; i++) { sd = &st->side_data[i]; if (sd->type == type) { av_freep(&sd->data); sd->data = data; sd->size = size; return 0; } } if (st->nb_side_data + 1U > FFMIN(INT_MAX, SIZE_MAX / sizeof(*tmp))) return AVERROR(ERANGE); tmp = av_realloc_array(st->side_data, st->nb_side_data + 1, sizeof(*tmp)); if (!tmp) { return AVERROR(ENOMEM); } st->side_data = tmp; st->nb_side_data++; sd = &st->side_data[st->nb_side_data - 1]; sd->type = type; sd->data = data; sd->size = size; return 0; } uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type, size_t size) { int ret; uint8_t *data = av_malloc(size); if (!data) return NULL; ret = av_stream_add_side_data(st, type, data, size); if (ret < 0) { av_freep(&data); return NULL; } return data; }