X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmp3enc.c;h=38a2665b22b0d7df01a5720efb9a42c9cf1dfbd8;hb=b10ba1175d3afa28d88cf3b24b69dc4882be16f5;hp=50342bb9509daaa83f6efccac44a448bbb981e9f;hpb=043d2affbbc124c6d802fe2989d9b1ed73825368;p=ffmpeg diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index 50342bb9509..38a2665b22b 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -21,10 +21,14 @@ #include #include "avformat.h" +#include "avio_internal.h" #include "id3v1.h" #include "id3v2.h" #include "rawenc.h" #include "libavutil/avstring.h" +#include "libavcodec/mpegaudio.h" +#include "libavcodec/mpegaudiodata.h" +#include "libavcodec/mpegaudiodecheader.h" #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "libavcodec/mpegaudio.h" @@ -132,51 +136,64 @@ static int id3v2_put_ttag(AVFormatContext *s, const char *str1, const char *str2 return len + ID3v2_HEADER_SIZE; } +#define VBR_NUM_BAGS 400 +#define VBR_TOC_SIZE 100 +typedef struct MP3Context { + const AVClass *class; + int id3v2_version; + int write_id3v1; + int64_t frames_offset; + int32_t frames; + int32_t size; + uint32_t want; + uint32_t seen; + uint32_t pos; + uint64_t bag[VBR_NUM_BAGS]; +} MP3Context; + static int mp2_write_trailer(struct AVFormatContext *s) { uint8_t buf[ID3v1_TAG_SIZE]; + MP3Context *mp3 = s->priv_data; /* write the id3v1 tag */ - if (id3v1_create_tag(s, buf) > 0) { + if (mp3 && mp3->write_id3v1 && id3v1_create_tag(s, buf) > 0) { avio_write(s->pb, buf, ID3v1_TAG_SIZE); - avio_flush(s->pb); } + + /* write number of frames */ + if (mp3 && mp3->frames_offset) { + avio_seek(s->pb, mp3->frames_offset, SEEK_SET); + avio_wb32(s->pb, s->streams[0]->nb_frames); + avio_seek(s->pb, 0, SEEK_END); + } + + avio_flush(s->pb); + return 0; } #if CONFIG_MP2_MUXER AVOutputFormat ff_mp2_muxer = { - "mp2", - NULL_IF_CONFIG_SMALL("MPEG audio layer 2"), - "audio/x-mpeg", - "mp2,m2a", - 0, - CODEC_ID_MP2, - CODEC_ID_NONE, - NULL, - ff_raw_write_packet, - mp2_write_trailer, + .name = "mp2", + .long_name = NULL_IF_CONFIG_SMALL("MPEG audio layer 2"), + .mime_type = "audio/x-mpeg", + .extensions = "mp2,m2a", + .audio_codec = CODEC_ID_MP2, + .video_codec = CODEC_ID_NONE, + .write_packet = ff_raw_write_packet, + .write_trailer = mp2_write_trailer, + .flags = AVFMT_NOTIMESTAMPS, }; #endif #if CONFIG_MP3_MUXER -#define VBR_NUM_BAGS 400 -#define VBR_TOC_SIZE 100 -typedef struct MP3Context { - const AVClass *class; - int id3v2_version; - int64_t frames_offset; - int32_t frames; - int32_t size; - uint32_t want; - uint32_t seen; - uint32_t pos; - uint64_t bag[VBR_NUM_BAGS]; -} MP3Context; static const AVOption options[] = { { "id3v2_version", "Select ID3v2 version to write. Currently 3 and 4 are supported.", offsetof(MP3Context, id3v2_version), FF_OPT_TYPE_INT, {.dbl = 4}, 3, 4, AV_OPT_FLAG_ENCODING_PARAM}, + { "write_id3v1", "Enable ID3v1 writing. ID3v1 tags are written in UTF-8 which may not be supported by most software.", + offsetof(MP3Context, write_id3v1), FF_OPT_TYPE_INT, {.dbl = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, { NULL }, }; @@ -444,17 +461,17 @@ static int mp3_write_trailer(AVFormatContext *s) } AVOutputFormat ff_mp3_muxer = { - "mp3", - NULL_IF_CONFIG_SMALL("MPEG audio layer 3"), - "audio/x-mpeg", - "mp3", - sizeof(MP3Context), - CODEC_ID_MP3, - CODEC_ID_NONE, - mp3_write_header, - mp3_write_packet, - mp3_write_trailer, - AVFMT_NOTIMESTAMPS, + .name = "mp3", + .long_name = NULL_IF_CONFIG_SMALL("MPEG audio layer 3"), + .mime_type = "audio/x-mpeg", + .extensions = "mp3", + .priv_data_size = sizeof(MP3Context), + .audio_codec = CODEC_ID_MP3, + .video_codec = CODEC_ID_NONE, + .write_header = mp3_write_header, + .write_packet = mp3_write_packet, + .write_trailer = mp3_write_trailer, + .flags = AVFMT_NOTIMESTAMPS, .priv_class = &mp3_muxer_class, }; #endif