Generalize RIFF INFO tag support; support reading INFO tag in wav
Signed-off-by: Ronald S. Bultje <rsbultje@gmail.com>
This commit is contained in:
parent
3f5aa7dfa6
commit
12bc20502a
@ -39,8 +39,8 @@ OBJS-$(CONFIG_ASS_DEMUXER) += assdec.o
|
|||||||
OBJS-$(CONFIG_ASS_MUXER) += assenc.o
|
OBJS-$(CONFIG_ASS_MUXER) += assenc.o
|
||||||
OBJS-$(CONFIG_AU_DEMUXER) += au.o pcm.o
|
OBJS-$(CONFIG_AU_DEMUXER) += au.o pcm.o
|
||||||
OBJS-$(CONFIG_AU_MUXER) += au.o
|
OBJS-$(CONFIG_AU_MUXER) += au.o
|
||||||
OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o riff.o avi.o
|
OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o riff.o
|
||||||
OBJS-$(CONFIG_AVI_MUXER) += avienc.o riff.o avi.o
|
OBJS-$(CONFIG_AVI_MUXER) += avienc.o riff.o
|
||||||
OBJS-$(CONFIG_AVISYNTH) += avisynth.o
|
OBJS-$(CONFIG_AVISYNTH) += avisynth.o
|
||||||
OBJS-$(CONFIG_AVM2_MUXER) += swfenc.o
|
OBJS-$(CONFIG_AVM2_MUXER) += swfenc.o
|
||||||
OBJS-$(CONFIG_AVS_DEMUXER) += avs.o vocdec.o voc.o
|
OBJS-$(CONFIG_AVS_DEMUXER) += avs.o vocdec.o voc.o
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* AVI common data
|
|
||||||
* Copyright (c) 2010 Anton Khirnov
|
|
||||||
*
|
|
||||||
* This file is part of Libav.
|
|
||||||
*
|
|
||||||
* Libav 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.
|
|
||||||
*
|
|
||||||
* Libav 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 Libav; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "avi.h"
|
|
||||||
|
|
||||||
const AVMetadataConv ff_avi_metadata_conv[] = {
|
|
||||||
{ "IART", "artist" },
|
|
||||||
{ "ICMT", "comment" },
|
|
||||||
{ "ICOP", "copyright" },
|
|
||||||
{ "ICRD", "date" },
|
|
||||||
{ "IGNR", "genre" },
|
|
||||||
{ "ILNG", "language" },
|
|
||||||
{ "INAM", "title" },
|
|
||||||
{ "IPRD", "album" },
|
|
||||||
{ "IPRT", "track" },
|
|
||||||
{ "ISFT", "encoder" },
|
|
||||||
{ "ITCH", "encoded_by"},
|
|
||||||
{ "strn", "title" },
|
|
||||||
{ 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
const char ff_avi_tags[][5] = {
|
|
||||||
"IARL", "IART", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI",
|
|
||||||
"IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD",
|
|
||||||
"IPRT", "ISBJ", "ISFT", "ISHP", "ISRC", "ISRF", "ITCH",
|
|
||||||
{0}
|
|
||||||
};
|
|
@ -21,8 +21,6 @@
|
|||||||
#ifndef AVFORMAT_AVI_H
|
#ifndef AVFORMAT_AVI_H
|
||||||
#define AVFORMAT_AVI_H
|
#define AVFORMAT_AVI_H
|
||||||
|
|
||||||
#include "metadata.h"
|
|
||||||
|
|
||||||
#define AVIF_HASINDEX 0x00000010 // Index at end of file?
|
#define AVIF_HASINDEX 0x00000010 // Index at end of file?
|
||||||
#define AVIF_MUSTUSEINDEX 0x00000020
|
#define AVIF_MUSTUSEINDEX 0x00000020
|
||||||
#define AVIF_ISINTERLEAVED 0x00000100
|
#define AVIF_ISINTERLEAVED 0x00000100
|
||||||
@ -37,11 +35,4 @@
|
|||||||
/* index flags */
|
/* index flags */
|
||||||
#define AVIIF_INDEX 0x10
|
#define AVIIF_INDEX 0x10
|
||||||
|
|
||||||
extern const AVMetadataConv ff_avi_metadata_conv[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of AVI info tags.
|
|
||||||
*/
|
|
||||||
extern const char ff_avi_tags[][5];
|
|
||||||
|
|
||||||
#endif /* AVFORMAT_AVI_H */
|
#endif /* AVFORMAT_AVI_H */
|
||||||
|
@ -79,6 +79,11 @@ static const char avi_headers[][8] = {
|
|||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const AVMetadataConv avi_metadata_conv[] = {
|
||||||
|
{ "strn", "title" },
|
||||||
|
{ 0 },
|
||||||
|
};
|
||||||
|
|
||||||
static int avi_load_index(AVFormatContext *s);
|
static int avi_load_index(AVFormatContext *s);
|
||||||
static int guess_ni_flag(AVFormatContext *s);
|
static int guess_ni_flag(AVFormatContext *s);
|
||||||
|
|
||||||
@ -261,15 +266,6 @@ static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag, uint32_t
|
|||||||
AV_DICT_DONT_STRDUP_VAL);
|
AV_DICT_DONT_STRDUP_VAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void avi_read_info(AVFormatContext *s, uint64_t end)
|
|
||||||
{
|
|
||||||
while (avio_tell(s->pb) < end) {
|
|
||||||
uint32_t tag = avio_rl32(s->pb);
|
|
||||||
uint32_t size = avio_rl32(s->pb);
|
|
||||||
avi_read_tag(s, NULL, tag, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char months[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
static const char months[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||||
|
|
||||||
@ -380,7 +376,7 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
|||||||
goto end_of_header;
|
goto end_of_header;
|
||||||
}
|
}
|
||||||
else if (tag1 == MKTAG('I', 'N', 'F', 'O'))
|
else if (tag1 == MKTAG('I', 'N', 'F', 'O'))
|
||||||
avi_read_info(s, list_end);
|
ff_read_riff_info(s, size - 4);
|
||||||
else if (tag1 == MKTAG('n', 'c', 'd', 't'))
|
else if (tag1 == MKTAG('n', 'c', 'd', 't'))
|
||||||
avi_read_nikon(s, list_end);
|
avi_read_nikon(s, list_end);
|
||||||
|
|
||||||
@ -745,7 +741,8 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
|||||||
clean_index(s);
|
clean_index(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
ff_metadata_conv_ctx(s, NULL, ff_avi_metadata_conv);
|
ff_metadata_conv_ctx(s, NULL, avi_metadata_conv);
|
||||||
|
ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -378,9 +378,9 @@ static int avi_write_header(AVFormatContext *s)
|
|||||||
|
|
||||||
list2 = ff_start_tag(pb, "LIST");
|
list2 = ff_start_tag(pb, "LIST");
|
||||||
ffio_wfourcc(pb, "INFO");
|
ffio_wfourcc(pb, "INFO");
|
||||||
ff_metadata_conv(&s->metadata, ff_avi_metadata_conv, NULL);
|
ff_metadata_conv(&s->metadata, ff_riff_info_conv, NULL);
|
||||||
for (i = 0; *ff_avi_tags[i]; i++) {
|
for (i = 0; *ff_riff_tags[i]; i++) {
|
||||||
if ((t = av_dict_get(s->metadata, ff_avi_tags[i], NULL, AV_DICT_MATCH_CASE)))
|
if ((t = av_dict_get(s->metadata, ff_riff_tags[i], NULL, AV_DICT_MATCH_CASE)))
|
||||||
avi_write_info_tag(s->pb, t->key, t->value);
|
avi_write_info_tag(s->pb, t->key, t->value);
|
||||||
}
|
}
|
||||||
ff_end_tag(pb, list2);
|
ff_end_tag(pb, list2);
|
||||||
|
@ -342,6 +342,28 @@ const AVCodecTag ff_codec_wav_tags[] = {
|
|||||||
{ CODEC_ID_NONE, 0 },
|
{ CODEC_ID_NONE, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const AVMetadataConv ff_riff_info_conv[] = {
|
||||||
|
{ "IART", "artist" },
|
||||||
|
{ "ICMT", "comment" },
|
||||||
|
{ "ICOP", "copyright" },
|
||||||
|
{ "ICRD", "date" },
|
||||||
|
{ "IGNR", "genre" },
|
||||||
|
{ "ILNG", "language" },
|
||||||
|
{ "INAM", "title" },
|
||||||
|
{ "IPRD", "album" },
|
||||||
|
{ "IPRT", "track" },
|
||||||
|
{ "ISFT", "encoder" },
|
||||||
|
{ "ITCH", "encoded_by"},
|
||||||
|
{ 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
const char ff_riff_tags[][5] = {
|
||||||
|
"IARL", "IART", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI",
|
||||||
|
"IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD",
|
||||||
|
"IPRT", "ISBJ", "ISFT", "ISHP", "ISRC", "ISRF", "ITCH",
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
#if CONFIG_MUXERS
|
#if CONFIG_MUXERS
|
||||||
int64_t ff_start_tag(AVIOContext *pb, const char *tag)
|
int64_t ff_start_tag(AVIOContext *pb, const char *tag)
|
||||||
{
|
{
|
||||||
@ -613,3 +635,49 @@ void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, int *au_ssiz
|
|||||||
*au_scale /= gcd;
|
*au_scale /= gcd;
|
||||||
*au_rate /= gcd;
|
*au_rate /= gcd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ff_read_riff_info(AVFormatContext *s, int64_t size)
|
||||||
|
{
|
||||||
|
int64_t start, end, cur;
|
||||||
|
AVIOContext *pb = s->pb;
|
||||||
|
|
||||||
|
start = avio_tell(pb);
|
||||||
|
end = start + size;
|
||||||
|
|
||||||
|
while ((cur = avio_tell(pb)) >= 0 && cur <= end - 8 /* = tag + size */) {
|
||||||
|
uint32_t chunk_code;
|
||||||
|
int64_t chunk_size;
|
||||||
|
char key[5] = {0};
|
||||||
|
char *value;
|
||||||
|
|
||||||
|
chunk_code = avio_rl32(pb);
|
||||||
|
chunk_size = avio_rl32(pb);
|
||||||
|
if (chunk_size > end || end - chunk_size < cur || chunk_size == UINT_MAX) {
|
||||||
|
av_log(s, AV_LOG_ERROR, "too big INFO subchunk\n");
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk_size += (chunk_size & 1);
|
||||||
|
|
||||||
|
value = av_malloc(chunk_size + 1);
|
||||||
|
if (!value) {
|
||||||
|
av_log(s, AV_LOG_ERROR, "out of memory, unable to read INFO tag\n");
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
AV_WL32(key, chunk_code);
|
||||||
|
|
||||||
|
if (avio_read(pb, value, chunk_size) != chunk_size) {
|
||||||
|
av_freep(key);
|
||||||
|
av_freep(value);
|
||||||
|
av_log(s, AV_LOG_ERROR, "premature end of file while reading INFO tag\n");
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
value[chunk_size] = 0;
|
||||||
|
|
||||||
|
av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -31,6 +31,10 @@
|
|||||||
#include "libavcodec/avcodec.h"
|
#include "libavcodec/avcodec.h"
|
||||||
#include "avio.h"
|
#include "avio.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "metadata.h"
|
||||||
|
|
||||||
|
extern const AVMetadataConv ff_riff_info_conv[];
|
||||||
|
extern const char ff_riff_tags[][5];
|
||||||
|
|
||||||
int64_t ff_start_tag(AVIOContext *pb, const char *tag);
|
int64_t ff_start_tag(AVIOContext *pb, const char *tag);
|
||||||
void ff_end_tag(AVIOContext *pb, int64_t start);
|
void ff_end_tag(AVIOContext *pb, int64_t start);
|
||||||
@ -54,4 +58,6 @@ unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum CodecID id);
|
|||||||
enum CodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag);
|
enum CodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag);
|
||||||
void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, int *au_ssize, int *au_scale);
|
void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, int *au_ssize, int *au_scale);
|
||||||
|
|
||||||
|
int ff_read_riff_info(AVFormatContext *s, int64_t size);
|
||||||
|
|
||||||
#endif /* AVFORMAT_RIFF_H */
|
#endif /* AVFORMAT_RIFF_H */
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#include "pcm.h"
|
#include "pcm.h"
|
||||||
#include "riff.h"
|
#include "riff.h"
|
||||||
#include "avio.h"
|
#include "avio.h"
|
||||||
#include "avio_internal.h"
|
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -224,7 +223,7 @@ AVOutputFormat ff_wav_muxer = {
|
|||||||
|
|
||||||
#if CONFIG_WAV_DEMUXER
|
#if CONFIG_WAV_DEMUXER
|
||||||
|
|
||||||
static int64_t next_tag(AVIOContext *pb, unsigned int *tag)
|
static int64_t next_tag(AVIOContext *pb, uint32_t *tag)
|
||||||
{
|
{
|
||||||
*tag = avio_rl32(pb);
|
*tag = avio_rl32(pb);
|
||||||
return avio_rl32(pb);
|
return avio_rl32(pb);
|
||||||
@ -385,7 +384,7 @@ static int wav_read_header(AVFormatContext *s,
|
|||||||
int64_t size, av_uninit(data_size);
|
int64_t size, av_uninit(data_size);
|
||||||
int64_t sample_count=0;
|
int64_t sample_count=0;
|
||||||
int rf64;
|
int rf64;
|
||||||
unsigned int tag;
|
uint32_t tag, list_type;
|
||||||
AVIOContext *pb = s->pb;
|
AVIOContext *pb = s->pb;
|
||||||
AVStream *st;
|
AVStream *st;
|
||||||
WAVContext *wav = s->priv_data;
|
WAVContext *wav = s->priv_data;
|
||||||
@ -467,6 +466,18 @@ static int wav_read_header(AVFormatContext *s,
|
|||||||
if ((ret = wav_parse_bext_tag(s, size)) < 0)
|
if ((ret = wav_parse_bext_tag(s, size)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
|
case MKTAG('L', 'I', 'S', 'T'):
|
||||||
|
list_type = avio_rl32(pb);
|
||||||
|
if (size <= 4) {
|
||||||
|
av_log(s, AV_LOG_ERROR, "too short LIST");
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
switch (list_type) {
|
||||||
|
case MKTAG('I', 'N', 'F', 'O'):
|
||||||
|
if ((ret = ff_read_riff_info(s, size - 4)) < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* seek to next tag unless we know that we'll run into EOF */
|
/* seek to next tag unless we know that we'll run into EOF */
|
||||||
@ -489,6 +500,7 @@ break_loop:
|
|||||||
st->duration = sample_count;
|
st->duration = sample_count;
|
||||||
|
|
||||||
ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);
|
ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);
|
||||||
|
ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user