ffmpeg/libavformat/demux_utils.c
Andreas Rheinhardt b800327f4c avformat/avformat: Add FFInputFormat, hide internals of AVInputFormat
This commit does for AVInputFormat what commit
59c9dc82f4 did for AVOutputFormat:
It adds a new type FFInputFormat, moves all the internals
of AVInputFormat to it and adds a now reduced AVInputFormat
as first member.

This does not affect/improve extensibility of both public
or private fields for demuxers (it is still a mess due to lavd).

This is possible since 50f34172e0
(which removed the last usage of an internal field of AVInputFormat
in fftools).

(Hint: tools/probetest.c accesses the internals of FFInputFormat
as well, but given that it is a testing tool this is not considered
a problem.)

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2024-03-07 08:53:31 -03:00

358 lines
12 KiB
C

/*
* Various utility demuxing functions
* 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/version.h"
#include "libavutil/avassert.h"
#include "libavcodec/bytestream.h"
#include "libavcodec/packet_internal.h"
#include "avformat.h"
#include "avio_internal.h"
#include "demux.h"
#include "internal.h"
struct AVCodecParserContext *av_stream_get_parser(const AVStream *st)
{
return cffstream(st)->parser;
}
void avpriv_stream_set_need_parsing(AVStream *st, enum AVStreamParseType type)
{
ffstream(st)->need_parsing = type;
}
AVChapter *avpriv_new_chapter(AVFormatContext *s, int64_t id, AVRational time_base,
int64_t start, int64_t end, const char *title)
{
FFFormatContext *const si = ffformatcontext(s);
AVChapter *chapter = NULL;
int ret;
if (end != AV_NOPTS_VALUE && start > end) {
av_log(s, AV_LOG_ERROR, "Chapter end time %"PRId64" before start %"PRId64"\n", end, start);
return NULL;
}
if (!s->nb_chapters) {
si->chapter_ids_monotonic = 1;
} else if (!si->chapter_ids_monotonic || s->chapters[s->nb_chapters-1]->id >= id) {
for (unsigned i = 0; i < s->nb_chapters; i++)
if (s->chapters[i]->id == id)
chapter = s->chapters[i];
if (!chapter)
si->chapter_ids_monotonic = 0;
}
if (!chapter) {
chapter = av_mallocz(sizeof(*chapter));
if (!chapter)
return NULL;
ret = av_dynarray_add_nofree(&s->chapters, &s->nb_chapters, chapter);
if (ret < 0) {
av_free(chapter);
return NULL;
}
}
av_dict_set(&chapter->metadata, "title", title, 0);
chapter->id = id;
chapter->time_base = time_base;
chapter->start = start;
chapter->end = end;
return chapter;
}
void av_format_inject_global_side_data(AVFormatContext *s)
{
FFFormatContext *const si = ffformatcontext(s);
si->inject_global_side_data = 1;
for (unsigned i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
ffstream(st)->inject_global_side_data = 1;
}
}
int avformat_queue_attached_pictures(AVFormatContext *s)
{
FFFormatContext *const si = ffformatcontext(s);
int ret;
for (unsigned i = 0; i < s->nb_streams; i++)
if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC &&
s->streams[i]->discard < AVDISCARD_ALL) {
if (s->streams[i]->attached_pic.size <= 0) {
av_log(s, AV_LOG_WARNING,
"Attached picture on stream %d has invalid size, "
"ignoring\n", i);
continue;
}
ret = avpriv_packet_list_put(&si->raw_packet_buffer,
&s->streams[i]->attached_pic,
av_packet_ref, 0);
if (ret < 0)
return ret;
}
return 0;
}
int ff_add_attached_pic(AVFormatContext *s, AVStream *st0, AVIOContext *pb,
AVBufferRef **buf, int size)
{
AVStream *st = st0;
AVPacket *pkt;
int ret;
if (!st && !(st = avformat_new_stream(s, NULL)))
return AVERROR(ENOMEM);
pkt = &st->attached_pic;
if (buf) {
av_assert1(*buf);
av_packet_unref(pkt);
pkt->buf = *buf;
pkt->data = (*buf)->data;
pkt->size = (*buf)->size - AV_INPUT_BUFFER_PADDING_SIZE;
*buf = NULL;
} else {
ret = av_get_packet(pb, pkt, size);
if (ret < 0)
goto fail;
}
st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
pkt->stream_index = st->index;
pkt->flags |= AV_PKT_FLAG_KEY;
return 0;
fail:
if (!st0)
ff_remove_stream(s, st);
return ret;
}
int ff_add_param_change(AVPacket *pkt, int32_t channels,
uint64_t channel_layout, int32_t sample_rate,
int32_t width, int32_t height)
{
uint32_t flags = 0;
int size = 4;
uint8_t *data;
if (!pkt)
return AVERROR(EINVAL);
if (sample_rate) {
size += 4;
flags |= AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE;
}
if (width || height) {
size += 8;
flags |= AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS;
}
data = av_packet_new_side_data(pkt, AV_PKT_DATA_PARAM_CHANGE, size);
if (!data)
return AVERROR(ENOMEM);
bytestream_put_le32(&data, flags);
if (sample_rate)
bytestream_put_le32(&data, sample_rate);
if (width || height) {
bytestream_put_le32(&data, width);
bytestream_put_le32(&data, height);
}
return 0;
}
int av_read_play(AVFormatContext *s)
{
if (ffifmt(s->iformat)->read_play)
return ffifmt(s->iformat)->read_play(s);
if (s->pb)
return avio_pause(s->pb, 0);
return AVERROR(ENOSYS);
}
int av_read_pause(AVFormatContext *s)
{
if (ffifmt(s->iformat)->read_pause)
return ffifmt(s->iformat)->read_pause(s);
if (s->pb)
return avio_pause(s->pb, 1);
return AVERROR(ENOSYS);
}
int ff_generate_avci_extradata(AVStream *st)
{
static const uint8_t avci100_1080p_extradata[] = {
// SPS
0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29,
0xb6, 0xd4, 0x20, 0x22, 0x33, 0x19, 0xc6, 0x63,
0x23, 0x21, 0x01, 0x11, 0x98, 0xce, 0x33, 0x19,
0x18, 0x21, 0x02, 0x56, 0xb9, 0x3d, 0x7d, 0x7e,
0x4f, 0xe3, 0x3f, 0x11, 0xf1, 0x9e, 0x08, 0xb8,
0x8c, 0x54, 0x43, 0xc0, 0x78, 0x02, 0x27, 0xe2,
0x70, 0x1e, 0x30, 0x10, 0x10, 0x14, 0x00, 0x00,
0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xca,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// PPS
0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x33, 0x48,
0xd0
};
static const uint8_t avci100_1080i_extradata[] = {
// SPS
0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29,
0xb6, 0xd4, 0x20, 0x22, 0x33, 0x19, 0xc6, 0x63,
0x23, 0x21, 0x01, 0x11, 0x98, 0xce, 0x33, 0x19,
0x18, 0x21, 0x03, 0x3a, 0x46, 0x65, 0x6a, 0x65,
0x24, 0xad, 0xe9, 0x12, 0x32, 0x14, 0x1a, 0x26,
0x34, 0xad, 0xa4, 0x41, 0x82, 0x23, 0x01, 0x50,
0x2b, 0x1a, 0x24, 0x69, 0x48, 0x30, 0x40, 0x2e,
0x11, 0x12, 0x08, 0xc6, 0x8c, 0x04, 0x41, 0x28,
0x4c, 0x34, 0xf0, 0x1e, 0x01, 0x13, 0xf2, 0xe0,
0x3c, 0x60, 0x20, 0x20, 0x28, 0x00, 0x00, 0x03,
0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0x94, 0x20,
// PPS
0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x33, 0x48,
0xd0
};
static const uint8_t avci50_1080p_extradata[] = {
// SPS
0x00, 0x00, 0x00, 0x01, 0x67, 0x6e, 0x10, 0x28,
0xa6, 0xd4, 0x20, 0x32, 0x33, 0x0c, 0x71, 0x18,
0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8c,
0x44, 0x30, 0x21, 0x02, 0x56, 0x4e, 0x6f, 0x37,
0xcd, 0xf9, 0xbf, 0x81, 0x6b, 0xf3, 0x7c, 0xde,
0x6e, 0x6c, 0xd3, 0x3c, 0x05, 0xa0, 0x22, 0x7e,
0x5f, 0xfc, 0x00, 0x0c, 0x00, 0x13, 0x8c, 0x04,
0x04, 0x05, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00,
0x00, 0x03, 0x00, 0x32, 0x84, 0x00, 0x00, 0x00,
// PPS
0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x31, 0x12,
0x11
};
static const uint8_t avci50_1080i_extradata[] = {
// SPS
0x00, 0x00, 0x00, 0x01, 0x67, 0x6e, 0x10, 0x28,
0xa6, 0xd4, 0x20, 0x32, 0x33, 0x0c, 0x71, 0x18,
0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8c,
0x44, 0x30, 0x21, 0x02, 0x56, 0x4e, 0x6e, 0x61,
0x87, 0x3e, 0x73, 0x4d, 0x98, 0x0c, 0x03, 0x06,
0x9c, 0x0b, 0x73, 0xe6, 0xc0, 0xb5, 0x18, 0x63,
0x0d, 0x39, 0xe0, 0x5b, 0x02, 0xd4, 0xc6, 0x19,
0x1a, 0x79, 0x8c, 0x32, 0x34, 0x24, 0xf0, 0x16,
0x81, 0x13, 0xf7, 0xff, 0x80, 0x02, 0x00, 0x01,
0xf1, 0x80, 0x80, 0x80, 0xa0, 0x00, 0x00, 0x03,
0x00, 0x20, 0x00, 0x00, 0x06, 0x50, 0x80, 0x00,
// PPS
0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x31, 0x12,
0x11
};
static const uint8_t avci100_720p_extradata[] = {
// SPS
0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29,
0xb6, 0xd4, 0x20, 0x2a, 0x33, 0x1d, 0xc7, 0x62,
0xa1, 0x08, 0x40, 0x54, 0x66, 0x3b, 0x8e, 0xc5,
0x42, 0x02, 0x10, 0x25, 0x64, 0x2c, 0x89, 0xe8,
0x85, 0xe4, 0x21, 0x4b, 0x90, 0x83, 0x06, 0x95,
0xd1, 0x06, 0x46, 0x97, 0x20, 0xc8, 0xd7, 0x43,
0x08, 0x11, 0xc2, 0x1e, 0x4c, 0x91, 0x0f, 0x01,
0x40, 0x16, 0xec, 0x07, 0x8c, 0x04, 0x04, 0x05,
0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03,
0x00, 0x64, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
// PPS
0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x31, 0x12,
0x11
};
static const uint8_t avci50_720p_extradata[] = {
// SPS
0x00, 0x00, 0x00, 0x01, 0x67, 0x6e, 0x10, 0x20,
0xa6, 0xd4, 0x20, 0x32, 0x33, 0x0c, 0x71, 0x18,
0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8c,
0x44, 0x30, 0x21, 0x02, 0x56, 0x4e, 0x6f, 0x37,
0xcd, 0xf9, 0xbf, 0x81, 0x6b, 0xf3, 0x7c, 0xde,
0x6e, 0x6c, 0xd3, 0x3c, 0x0f, 0x01, 0x6e, 0xff,
0xc0, 0x00, 0xc0, 0x01, 0x38, 0xc0, 0x40, 0x40,
0x50, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00,
0x06, 0x48, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
// PPS
0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x31, 0x12,
0x11
};
const uint8_t *data = NULL;
int ret, size = 0;
if (st->codecpar->width == 1920) {
if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) {
data = avci100_1080p_extradata;
size = sizeof(avci100_1080p_extradata);
} else {
data = avci100_1080i_extradata;
size = sizeof(avci100_1080i_extradata);
}
} else if (st->codecpar->width == 1440) {
if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) {
data = avci50_1080p_extradata;
size = sizeof(avci50_1080p_extradata);
} else {
data = avci50_1080i_extradata;
size = sizeof(avci50_1080i_extradata);
}
} else if (st->codecpar->width == 1280) {
data = avci100_720p_extradata;
size = sizeof(avci100_720p_extradata);
} else if (st->codecpar->width == 960) {
data = avci50_720p_extradata;
size = sizeof(avci50_720p_extradata);
}
if (!size)
return 0;
if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0)
return ret;
memcpy(st->codecpar->extradata, data, size);
return 0;
}
int ff_get_extradata(void *logctx, AVCodecParameters *par, AVIOContext *pb, int size)
{
int ret = ff_alloc_extradata(par, size);
if (ret < 0)
return ret;
ret = ffio_read_size(pb, par->extradata, size);
if (ret < 0) {
av_freep(&par->extradata);
par->extradata_size = 0;
av_log(logctx, AV_LOG_ERROR, "Failed to read extradata of size %d\n", size);
return ret;
}
return ret;
}
int ff_find_stream_index(const AVFormatContext *s, int id)
{
for (unsigned i = 0; i < s->nb_streams; i++)
if (s->streams[i]->id == id)
return i;
return -1;
}