mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
avformat/vorbiscomment: Switch to AVIOContext from bytestream API
Up until now ff_vorbiscomment_write() used the bytestream API to write VorbisComments. Therefore the caller had to provide a sufficiently large buffer to write the output. Yet two of the three callers (namely the FLAC and the Matroska muxer) actually want the output to be written via an AVIOContext; therefore they allocated buffers of the right size just for this purpose (i.e. they get freed immediately afterwards). Only the Ogg muxer actually wants a buffer. But given that it is easy to wrap a buffer into an AVIOContext this commit changes ff_vorbiscomment_write() to use an AVIOContext for its output. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
This commit is contained in:
parent
704d7c9f46
commit
6397b4d6a2
@ -29,7 +29,6 @@
|
|||||||
#include "id3v2.h"
|
#include "id3v2.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "vorbiscomment.h"
|
#include "vorbiscomment.h"
|
||||||
#include "libavcodec/bytestream.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct FlacMuxerContext {
|
typedef struct FlacMuxerContext {
|
||||||
@ -62,25 +61,16 @@ static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m,
|
|||||||
{
|
{
|
||||||
const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
|
const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
|
||||||
int64_t len;
|
int64_t len;
|
||||||
uint8_t *p, *p0;
|
|
||||||
|
|
||||||
ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
|
ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
|
||||||
|
|
||||||
len = ff_vorbiscomment_length(*m, vendor, NULL, 0);
|
len = ff_vorbiscomment_length(*m, vendor, NULL, 0);
|
||||||
if (len >= ((1<<24) - 4))
|
if (len >= ((1<<24) - 4))
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
p0 = av_malloc(len+4);
|
|
||||||
if (!p0)
|
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
p = p0;
|
|
||||||
|
|
||||||
bytestream_put_byte(&p, last_block ? 0x84 : 0x04);
|
avio_w8(pb, last_block ? 0x84 : 0x04);
|
||||||
bytestream_put_be24(&p, len);
|
avio_wb24(pb, len);
|
||||||
ff_vorbiscomment_write(&p, *m, vendor, NULL, 0);
|
ff_vorbiscomment_write(pb, *m, vendor, NULL, 0);
|
||||||
|
|
||||||
avio_write(pb, p0, len+4);
|
|
||||||
av_freep(&p0);
|
|
||||||
p = NULL;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -624,7 +624,7 @@ static int put_flac_codecpriv(AVFormatContext *s, AVIOContext *pb,
|
|||||||
const char *vendor = (s->flags & AVFMT_FLAG_BITEXACT) ?
|
const char *vendor = (s->flags & AVFMT_FLAG_BITEXACT) ?
|
||||||
"Lavf" : LIBAVFORMAT_IDENT;
|
"Lavf" : LIBAVFORMAT_IDENT;
|
||||||
AVDictionary *dict = NULL;
|
AVDictionary *dict = NULL;
|
||||||
uint8_t buf[32], *data, *p;
|
uint8_t buf[32];
|
||||||
int64_t len;
|
int64_t len;
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "0x%"PRIx64, par->channel_layout);
|
snprintf(buf, sizeof(buf), "0x%"PRIx64, par->channel_layout);
|
||||||
@ -633,21 +633,11 @@ static int put_flac_codecpriv(AVFormatContext *s, AVIOContext *pb,
|
|||||||
len = ff_vorbiscomment_length(dict, vendor, NULL, 0);
|
len = ff_vorbiscomment_length(dict, vendor, NULL, 0);
|
||||||
av_assert1(len < (1 << 24) - 4);
|
av_assert1(len < (1 << 24) - 4);
|
||||||
|
|
||||||
data = av_malloc(len + 4);
|
avio_w8(pb, 0x84);
|
||||||
if (!data) {
|
avio_wb24(pb, len);
|
||||||
av_dict_free(&dict);
|
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
data[0] = 0x84;
|
ff_vorbiscomment_write(pb, dict, vendor, NULL, 0);
|
||||||
AV_WB24(data + 1, len);
|
|
||||||
|
|
||||||
p = data + 4;
|
|
||||||
ff_vorbiscomment_write(&p, dict, vendor, NULL, 0);
|
|
||||||
|
|
||||||
avio_write(pb, data, len + 4);
|
|
||||||
|
|
||||||
av_freep(&data);
|
|
||||||
av_dict_free(&dict);
|
av_dict_free(&dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,8 +294,9 @@ static uint8_t *ogg_write_vorbiscomment(int64_t offset, int bitexact,
|
|||||||
AVChapter **chapters, unsigned int nb_chapters)
|
AVChapter **chapters, unsigned int nb_chapters)
|
||||||
{
|
{
|
||||||
const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
|
const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
|
||||||
|
AVIOContext pb;
|
||||||
int64_t size;
|
int64_t size;
|
||||||
uint8_t *p, *p0;
|
uint8_t *p;
|
||||||
|
|
||||||
ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
|
ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
|
||||||
|
|
||||||
@ -305,15 +306,14 @@ static uint8_t *ogg_write_vorbiscomment(int64_t offset, int bitexact,
|
|||||||
p = av_mallocz(size);
|
p = av_mallocz(size);
|
||||||
if (!p)
|
if (!p)
|
||||||
return NULL;
|
return NULL;
|
||||||
p0 = p;
|
|
||||||
|
|
||||||
p += offset;
|
ffio_init_context(&pb, p + offset, size - offset, 1, NULL, NULL, NULL, NULL);
|
||||||
ff_vorbiscomment_write(&p, *m, vendor, chapters, nb_chapters);
|
ff_vorbiscomment_write(&pb, *m, vendor, chapters, nb_chapters);
|
||||||
if (framing_bit)
|
if (framing_bit)
|
||||||
bytestream_put_byte(&p, 1);
|
avio_w8(&pb, 1);
|
||||||
|
|
||||||
*header_len = size;
|
*header_len = size;
|
||||||
return p0;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ogg_build_flac_headers(AVCodecParameters *par,
|
static int ogg_build_flac_headers(AVCodecParameters *par,
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
* 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 "avio.h"
|
||||||
#include "avformat.h"
|
#include "avformat.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "vorbiscomment.h"
|
#include "vorbiscomment.h"
|
||||||
#include "libavcodec/bytestream.h"
|
|
||||||
#include "libavutil/dict.h"
|
#include "libavutil/dict.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,13 +62,13 @@ int64_t ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ff_vorbiscomment_write(uint8_t **p, const AVDictionary *m,
|
int ff_vorbiscomment_write(AVIOContext *pb, const AVDictionary *m,
|
||||||
const char *vendor_string,
|
const char *vendor_string,
|
||||||
AVChapter **chapters, unsigned int nb_chapters)
|
AVChapter **chapters, unsigned int nb_chapters)
|
||||||
{
|
{
|
||||||
int cm_count = 0;
|
int cm_count = 0;
|
||||||
bytestream_put_le32(p, strlen(vendor_string));
|
avio_wl32(pb, strlen(vendor_string));
|
||||||
bytestream_put_buffer(p, vendor_string, strlen(vendor_string));
|
avio_write(pb, vendor_string, strlen(vendor_string));
|
||||||
if (chapters && nb_chapters) {
|
if (chapters && nb_chapters) {
|
||||||
for (int i = 0; i < nb_chapters; i++) {
|
for (int i = 0; i < nb_chapters; i++) {
|
||||||
cm_count += av_dict_count(chapters[i]->metadata) + 1;
|
cm_count += av_dict_count(chapters[i]->metadata) + 1;
|
||||||
@ -77,16 +77,16 @@ int ff_vorbiscomment_write(uint8_t **p, const AVDictionary *m,
|
|||||||
if (m) {
|
if (m) {
|
||||||
int count = av_dict_count(m) + cm_count;
|
int count = av_dict_count(m) + cm_count;
|
||||||
AVDictionaryEntry *tag = NULL;
|
AVDictionaryEntry *tag = NULL;
|
||||||
bytestream_put_le32(p, count);
|
avio_wl32(pb, count);
|
||||||
while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) {
|
while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) {
|
||||||
int64_t len1 = strlen(tag->key);
|
int64_t len1 = strlen(tag->key);
|
||||||
int64_t len2 = strlen(tag->value);
|
int64_t len2 = strlen(tag->value);
|
||||||
if (len1+1+len2 > UINT32_MAX)
|
if (len1+1+len2 > UINT32_MAX)
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
bytestream_put_le32(p, len1+1+len2);
|
avio_wl32(pb, len1 + 1 + len2);
|
||||||
bytestream_put_buffer(p, tag->key, len1);
|
avio_write(pb, tag->key, len1);
|
||||||
bytestream_put_byte(p, '=');
|
avio_w8(pb, '=');
|
||||||
bytestream_put_buffer(p, tag->value, len2);
|
avio_write(pb, tag->value, len2);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < nb_chapters; i++) {
|
for (int i = 0; i < nb_chapters; i++) {
|
||||||
AVChapter *chp = chapters[i];
|
AVChapter *chp = chapters[i];
|
||||||
@ -101,11 +101,11 @@ int ff_vorbiscomment_write(uint8_t **p, const AVDictionary *m,
|
|||||||
s = s % 60;
|
s = s % 60;
|
||||||
snprintf(chapter_number, sizeof(chapter_number), "%03d", i);
|
snprintf(chapter_number, sizeof(chapter_number), "%03d", i);
|
||||||
snprintf(chapter_time, sizeof(chapter_time), "%02d:%02d:%02d.%03d", h, m, s, ms);
|
snprintf(chapter_time, sizeof(chapter_time), "%02d:%02d:%02d.%03d", h, m, s, ms);
|
||||||
bytestream_put_le32(p, 10+1+12);
|
avio_wl32(pb, 10 + 1 + 12);
|
||||||
bytestream_put_buffer(p, "CHAPTER", 7);
|
avio_write(pb, "CHAPTER", 7);
|
||||||
bytestream_put_buffer(p, chapter_number, 3);
|
avio_write(pb, chapter_number, 3);
|
||||||
bytestream_put_byte(p, '=');
|
avio_w8(pb, '=');
|
||||||
bytestream_put_buffer(p, chapter_time, 12);
|
avio_write(pb, chapter_time, 12);
|
||||||
|
|
||||||
tag = NULL;
|
tag = NULL;
|
||||||
while ((tag = av_dict_get(chapters[i]->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
|
while ((tag = av_dict_get(chapters[i]->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
|
||||||
@ -113,18 +113,18 @@ int ff_vorbiscomment_write(uint8_t **p, const AVDictionary *m,
|
|||||||
int64_t len2 = strlen(tag->value);
|
int64_t len2 = strlen(tag->value);
|
||||||
if (len1+1+len2+10 > UINT32_MAX)
|
if (len1+1+len2+10 > UINT32_MAX)
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
bytestream_put_le32(p, 10+len1+1+len2);
|
avio_wl32(pb, 10 + len1 + 1 + len2);
|
||||||
bytestream_put_buffer(p, "CHAPTER", 7);
|
avio_write(pb, "CHAPTER", 7);
|
||||||
bytestream_put_buffer(p, chapter_number, 3);
|
avio_write(pb, chapter_number, 3);
|
||||||
if (!strcmp(tag->key, "title"))
|
if (!strcmp(tag->key, "title"))
|
||||||
bytestream_put_buffer(p, "NAME", 4);
|
avio_write(pb, "NAME", 4);
|
||||||
else
|
else
|
||||||
bytestream_put_buffer(p, tag->key, len1);
|
avio_write(pb, tag->key, len1);
|
||||||
bytestream_put_byte(p, '=');
|
avio_w8(pb, '=');
|
||||||
bytestream_put_buffer(p, tag->value, len2);
|
avio_write(pb, tag->value, len2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
bytestream_put_le32(p, 0);
|
avio_wl32(pb, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -38,18 +38,17 @@ int64_t ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string
|
|||||||
AVChapter **chapters, unsigned int nb_chapters);
|
AVChapter **chapters, unsigned int nb_chapters);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a VorbisComment into a buffer. The buffer, p, must have enough
|
* Write a VorbisComment into an AVIOContext. The output size can be obtained
|
||||||
* data to hold the whole VorbisComment. The minimum size required can be
|
* in advance by passing the same chapters, AVDictionary and vendor_string to
|
||||||
* obtained by passing the same AVDictionary and vendor_string to
|
|
||||||
* ff_vorbiscomment_length()
|
* ff_vorbiscomment_length()
|
||||||
*
|
*
|
||||||
* @param p The buffer in which to write.
|
* @param pb The AVIOContext to write the output.
|
||||||
* @param m The metadata struct to write.
|
* @param m The metadata struct to write.
|
||||||
* @param vendor_string The vendor string to write.
|
* @param vendor_string The vendor string to write.
|
||||||
* @param chapters The chapters to write.
|
* @param chapters The chapters to write.
|
||||||
* @param nb_chapters The number of chapters to write.
|
* @param nb_chapters The number of chapters to write.
|
||||||
*/
|
*/
|
||||||
int ff_vorbiscomment_write(uint8_t **p, const AVDictionary *m,
|
int ff_vorbiscomment_write(AVIOContext *pb, const AVDictionary *m,
|
||||||
const char *vendor_string,
|
const char *vendor_string,
|
||||||
AVChapter **chapters, unsigned int nb_chapters);
|
AVChapter **chapters, unsigned int nb_chapters);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user