mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-04-14 00:58:38 +02:00
Use a shared function to validate FLAC extradata.
Originally committed as revision 17602 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
caee91f7d0
commit
59c6178a54
@ -345,15 +345,16 @@ OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcm.o
|
|||||||
|
|
||||||
# libavformat dependencies
|
# libavformat dependencies
|
||||||
OBJS-$(CONFIG_EAC3_DEMUXER) += ac3_parser.o ac3tab.o aac_ac3_parser.o
|
OBJS-$(CONFIG_EAC3_DEMUXER) += ac3_parser.o ac3tab.o aac_ac3_parser.o
|
||||||
|
OBJS-$(CONFIG_FLAC_MUXER) += flacdec.o
|
||||||
OBJS-$(CONFIG_GXF_DEMUXER) += mpeg12data.o
|
OBJS-$(CONFIG_GXF_DEMUXER) += mpeg12data.o
|
||||||
OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += xiph.o mpeg4audio.o
|
OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += xiph.o mpeg4audio.o flacdec.o
|
||||||
OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o
|
OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o
|
||||||
OBJS-$(CONFIG_MATROSKA_MUXER) += xiph.o mpeg4audio.o
|
OBJS-$(CONFIG_MATROSKA_MUXER) += xiph.o mpeg4audio.o flacdec.o
|
||||||
OBJS-$(CONFIG_MOV_DEMUXER) += mpeg4audio.o mpegaudiodata.o
|
OBJS-$(CONFIG_MOV_DEMUXER) += mpeg4audio.o mpegaudiodata.o
|
||||||
OBJS-$(CONFIG_MPEGTS_MUXER) += mpegvideo.o
|
OBJS-$(CONFIG_MPEGTS_MUXER) += mpegvideo.o
|
||||||
OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o
|
OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o
|
||||||
OBJS-$(CONFIG_OGG_DEMUXER) += flacdec.o
|
OBJS-$(CONFIG_OGG_DEMUXER) += flacdec.o
|
||||||
OBJS-$(CONFIG_OGG_MUXER) += xiph.o
|
OBJS-$(CONFIG_OGG_MUXER) += xiph.o flacdec.o
|
||||||
OBJS-$(CONFIG_RTP_MUXER) += mpegvideo.o
|
OBJS-$(CONFIG_RTP_MUXER) += mpegvideo.o
|
||||||
|
|
||||||
# external codec libraries
|
# external codec libraries
|
||||||
|
@ -42,6 +42,11 @@ enum {
|
|||||||
FLAC_METADATA_TYPE_INVALID = 127
|
FLAC_METADATA_TYPE_INVALID = 127
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum FLACExtradataFormat {
|
||||||
|
FLAC_EXTRADATA_FORMAT_STREAMINFO = 0,
|
||||||
|
FLAC_EXTRADATA_FORMAT_FULL_HEADER = 1
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data needed from the Streaminfo header for use by the raw FLAC demuxer
|
* Data needed from the Streaminfo header for use by the raw FLAC demuxer
|
||||||
* and/or the FLAC decoder.
|
* and/or the FLAC decoder.
|
||||||
@ -68,4 +73,15 @@ typedef struct FLACStreaminfo {
|
|||||||
void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
|
void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
|
||||||
const uint8_t *buffer);
|
const uint8_t *buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the FLAC extradata.
|
||||||
|
* @param[in] avctx codec context containing the extradata.
|
||||||
|
* @param[out] format extradata format.
|
||||||
|
* @param[out] streaminfo_start pointer to start of 34-byte STREAMINFO data.
|
||||||
|
* @return 1 if valid, 0 if not valid.
|
||||||
|
*/
|
||||||
|
int ff_flac_is_extradata_valid(AVCodecContext *avctx,
|
||||||
|
enum FLACExtradataFormat *format,
|
||||||
|
uint8_t **streaminfo_start);
|
||||||
|
|
||||||
#endif /* AVCODEC_FLAC_H */
|
#endif /* AVCODEC_FLAC_H */
|
||||||
|
@ -96,26 +96,55 @@ static int64_t get_utf8(GetBitContext *gb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void allocate_buffers(FLACContext *s);
|
static void allocate_buffers(FLACContext *s);
|
||||||
static int metadata_parse(FLACContext *s);
|
|
||||||
|
int ff_flac_is_extradata_valid(AVCodecContext *avctx,
|
||||||
|
enum FLACExtradataFormat *format,
|
||||||
|
uint8_t **streaminfo_start)
|
||||||
|
{
|
||||||
|
if (!avctx->extradata || avctx->extradata_size < FLAC_STREAMINFO_SIZE) {
|
||||||
|
av_log(avctx, AV_LOG_ERROR, "extradata NULL or too small.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (AV_RL32(avctx->extradata) != MKTAG('f','L','a','C')) {
|
||||||
|
/* extradata contains STREAMINFO only */
|
||||||
|
if (avctx->extradata_size != FLAC_STREAMINFO_SIZE) {
|
||||||
|
av_log(avctx, AV_LOG_WARNING, "extradata contains %d bytes too many.\n",
|
||||||
|
FLAC_STREAMINFO_SIZE-avctx->extradata_size);
|
||||||
|
}
|
||||||
|
*format = FLAC_EXTRADATA_FORMAT_STREAMINFO;
|
||||||
|
*streaminfo_start = avctx->extradata;
|
||||||
|
} else {
|
||||||
|
if (avctx->extradata_size < 8+FLAC_STREAMINFO_SIZE) {
|
||||||
|
av_log(avctx, AV_LOG_ERROR, "extradata too small.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*format = FLAC_EXTRADATA_FORMAT_FULL_HEADER;
|
||||||
|
*streaminfo_start = &avctx->extradata[8];
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static av_cold int flac_decode_init(AVCodecContext *avctx)
|
static av_cold int flac_decode_init(AVCodecContext *avctx)
|
||||||
{
|
{
|
||||||
|
enum FLACExtradataFormat format;
|
||||||
|
uint8_t *streaminfo;
|
||||||
FLACContext *s = avctx->priv_data;
|
FLACContext *s = avctx->priv_data;
|
||||||
s->avctx = avctx;
|
s->avctx = avctx;
|
||||||
|
|
||||||
avctx->sample_fmt = SAMPLE_FMT_S16;
|
avctx->sample_fmt = SAMPLE_FMT_S16;
|
||||||
|
|
||||||
if (avctx->extradata_size > 4) {
|
/* for now, the raw FLAC header is allowed to be passed to the decoder as
|
||||||
|
frame data instead of extradata. */
|
||||||
|
if (!avctx->extradata)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!ff_flac_is_extradata_valid(avctx, &format, &streaminfo))
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* initialize based on the demuxer-supplied streamdata header */
|
/* initialize based on the demuxer-supplied streamdata header */
|
||||||
if (avctx->extradata_size == FLAC_STREAMINFO_SIZE) {
|
|
||||||
ff_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s,
|
ff_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s,
|
||||||
avctx->extradata);
|
streaminfo);
|
||||||
allocate_buffers(s);
|
allocate_buffers(s);
|
||||||
} else {
|
|
||||||
init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size*8);
|
|
||||||
metadata_parse(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "libavcodec/flac.h"
|
||||||
#include "avformat.h"
|
#include "avformat.h"
|
||||||
|
|
||||||
static int flac_write_header(struct AVFormatContext *s)
|
static int flac_write_header(struct AVFormatContext *s)
|
||||||
@ -26,9 +27,15 @@ static int flac_write_header(struct AVFormatContext *s)
|
|||||||
static const uint8_t header[8] = {
|
static const uint8_t header[8] = {
|
||||||
0x66, 0x4C, 0x61, 0x43, 0x80, 0x00, 0x00, 0x22
|
0x66, 0x4C, 0x61, 0x43, 0x80, 0x00, 0x00, 0x22
|
||||||
};
|
};
|
||||||
uint8_t *streaminfo = s->streams[0]->codec->extradata;
|
AVCodecContext *codec = s->streams[0]->codec;
|
||||||
|
uint8_t *streaminfo;
|
||||||
int len = s->streams[0]->codec->extradata_size;
|
int len = s->streams[0]->codec->extradata_size;
|
||||||
if(streaminfo != NULL && len > 0) {
|
enum FLACExtradataFormat format;
|
||||||
|
|
||||||
|
if (!ff_flac_is_extradata_valid(codec, &format, &streaminfo))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (format == FLAC_EXTRADATA_FORMAT_STREAMINFO) {
|
||||||
put_buffer(s->pb, header, 8);
|
put_buffer(s->pb, header, 8);
|
||||||
put_buffer(s->pb, streaminfo, len);
|
put_buffer(s->pb, streaminfo, len);
|
||||||
}
|
}
|
||||||
@ -38,16 +45,22 @@ static int flac_write_header(struct AVFormatContext *s)
|
|||||||
static int flac_write_trailer(struct AVFormatContext *s)
|
static int flac_write_trailer(struct AVFormatContext *s)
|
||||||
{
|
{
|
||||||
ByteIOContext *pb = s->pb;
|
ByteIOContext *pb = s->pb;
|
||||||
uint8_t *streaminfo = s->streams[0]->codec->extradata;
|
uint8_t *streaminfo;
|
||||||
int len = s->streams[0]->codec->extradata_size;
|
enum FLACExtradataFormat format;
|
||||||
int64_t file_size;
|
int64_t file_size;
|
||||||
|
|
||||||
if (streaminfo && len > 0 && !url_is_streamed(s->pb)) {
|
if (!ff_flac_is_extradata_valid(s->streams[0]->codec, &format, &streaminfo))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!url_is_streamed(pb)) {
|
||||||
|
/* rewrite the STREAMINFO header block data */
|
||||||
file_size = url_ftell(pb);
|
file_size = url_ftell(pb);
|
||||||
url_fseek(pb, 8, SEEK_SET);
|
url_fseek(pb, 8, SEEK_SET);
|
||||||
put_buffer(pb, streaminfo, len);
|
put_buffer(pb, streaminfo, FLAC_STREAMINFO_SIZE);
|
||||||
url_fseek(pb, file_size, SEEK_SET);
|
url_fseek(pb, file_size, SEEK_SET);
|
||||||
put_flush_packet(pb);
|
put_flush_packet(pb);
|
||||||
|
} else {
|
||||||
|
av_log(s, AV_LOG_WARNING, "unable to rewrite FLAC header.\n");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "libavutil/md5.h"
|
#include "libavutil/md5.h"
|
||||||
#include "libavcodec/xiph.h"
|
#include "libavcodec/xiph.h"
|
||||||
#include "libavcodec/mpeg4audio.h"
|
#include "libavcodec/mpeg4audio.h"
|
||||||
|
#include "libavcodec/flac.h"
|
||||||
|
|
||||||
typedef struct ebml_master {
|
typedef struct ebml_master {
|
||||||
int64_t pos; ///< absolute offset in the file where the master's elements start
|
int64_t pos; ///< absolute offset in the file where the master's elements start
|
||||||
@ -420,23 +421,20 @@ static int put_xiph_codecpriv(AVFormatContext *s, ByteIOContext *pb, AVCodecCont
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FLAC_STREAMINFO_SIZE 34
|
|
||||||
|
|
||||||
static int put_flac_codecpriv(AVFormatContext *s, ByteIOContext *pb, AVCodecContext *codec)
|
static int put_flac_codecpriv(AVFormatContext *s, ByteIOContext *pb, AVCodecContext *codec)
|
||||||
{
|
{
|
||||||
// if the extradata_size is greater than FLAC_STREAMINFO_SIZE,
|
uint8_t *streaminfo;
|
||||||
// assume that it's in Matroska format already
|
enum FLACExtradataFormat format;
|
||||||
if (codec->extradata_size < FLAC_STREAMINFO_SIZE) {
|
|
||||||
|
if (!ff_flac_is_extradata_valid(codec, &format, &streaminfo)) {
|
||||||
av_log(s, AV_LOG_ERROR, "Invalid FLAC extradata\n");
|
av_log(s, AV_LOG_ERROR, "Invalid FLAC extradata\n");
|
||||||
return -1;
|
return -1;
|
||||||
} else if (codec->extradata_size == FLAC_STREAMINFO_SIZE) {
|
}
|
||||||
|
if (format == FLAC_EXTRADATA_FORMAT_STREAMINFO) {
|
||||||
// only the streaminfo packet
|
// only the streaminfo packet
|
||||||
put_buffer(pb, "fLaC", 4);
|
put_buffer(pb, "fLaC", 4);
|
||||||
put_byte(pb, 0x80);
|
put_byte(pb, 0x80);
|
||||||
put_be24(pb, FLAC_STREAMINFO_SIZE);
|
put_be24(pb, FLAC_STREAMINFO_SIZE);
|
||||||
} else if(memcmp("fLaC", codec->extradata, 4)) {
|
|
||||||
av_log(s, AV_LOG_ERROR, "Invalid FLAC extradata\n");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
put_buffer(pb, codec->extradata, codec->extradata_size);
|
put_buffer(pb, codec->extradata, codec->extradata_size);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "libavutil/crc.h"
|
#include "libavutil/crc.h"
|
||||||
#include "libavcodec/xiph.h"
|
#include "libavcodec/xiph.h"
|
||||||
#include "libavcodec/bytestream.h"
|
#include "libavcodec/bytestream.h"
|
||||||
|
#include "libavcodec/flac.h"
|
||||||
#include "avformat.h"
|
#include "avformat.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@ -82,12 +83,14 @@ static int ogg_write_page(AVFormatContext *s, const uint8_t *data, int size,
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ogg_build_flac_headers(const uint8_t *extradata, int extradata_size,
|
static int ogg_build_flac_headers(AVCodecContext *avctx,
|
||||||
OGGStreamContext *oggstream, int bitexact)
|
OGGStreamContext *oggstream, int bitexact)
|
||||||
{
|
{
|
||||||
const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
|
const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
|
||||||
|
enum FLACExtradataFormat format;
|
||||||
|
uint8_t *streaminfo;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
if (extradata_size != 34)
|
if (!ff_flac_is_extradata_valid(avctx, &format, &streaminfo))
|
||||||
return -1;
|
return -1;
|
||||||
oggstream->header_len[0] = 51;
|
oggstream->header_len[0] = 51;
|
||||||
oggstream->header[0] = av_mallocz(51); // per ogg flac specs
|
oggstream->header[0] = av_mallocz(51); // per ogg flac specs
|
||||||
@ -100,7 +103,7 @@ static int ogg_build_flac_headers(const uint8_t *extradata, int extradata_size,
|
|||||||
bytestream_put_buffer(&p, "fLaC", 4);
|
bytestream_put_buffer(&p, "fLaC", 4);
|
||||||
bytestream_put_byte(&p, 0x00); // streaminfo
|
bytestream_put_byte(&p, 0x00); // streaminfo
|
||||||
bytestream_put_be24(&p, 34);
|
bytestream_put_be24(&p, 34);
|
||||||
bytestream_put_buffer(&p, extradata, 34);
|
bytestream_put_buffer(&p, streaminfo, FLAC_STREAMINFO_SIZE);
|
||||||
oggstream->header_len[1] = 1+3+4+strlen(vendor)+4;
|
oggstream->header_len[1] = 1+3+4+strlen(vendor)+4;
|
||||||
oggstream->header[1] = av_mallocz(oggstream->header_len[1]);
|
oggstream->header[1] = av_mallocz(oggstream->header_len[1]);
|
||||||
p = oggstream->header[1];
|
p = oggstream->header[1];
|
||||||
@ -136,7 +139,7 @@ static int ogg_write_header(AVFormatContext *s)
|
|||||||
oggstream = av_mallocz(sizeof(*oggstream));
|
oggstream = av_mallocz(sizeof(*oggstream));
|
||||||
st->priv_data = oggstream;
|
st->priv_data = oggstream;
|
||||||
if (st->codec->codec_id == CODEC_ID_FLAC) {
|
if (st->codec->codec_id == CODEC_ID_FLAC) {
|
||||||
if (ogg_build_flac_headers(st->codec->extradata, st->codec->extradata_size,
|
if (ogg_build_flac_headers(st->codec,
|
||||||
oggstream, st->codec->flags & CODEC_FLAG_BITEXACT) < 0) {
|
oggstream, st->codec->flags & CODEC_FLAG_BITEXACT) < 0) {
|
||||||
av_log(s, AV_LOG_ERROR, "Extradata corrupted\n");
|
av_log(s, AV_LOG_ERROR, "Extradata corrupted\n");
|
||||||
av_freep(&st->priv_data);
|
av_freep(&st->priv_data);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user