mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-26 19:01:44 +02:00
790f793844
There are lots of files that don't need it: The number of object files that actually need it went down from 2011 to 884 here. Keep it for external users in order to not cause breakages. Also improve the other headers a bit while just at it. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
358 lines
12 KiB
C
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/mem.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;
|
|
}
|