]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/mp3enc.c
fate: add h264 intra 4:2:2 tests
[ffmpeg] / libavformat / mp3enc.c
index 2775eb8fc8b54224e5b381f73beb3c0b99bf405b..7e96d47995d7adb0b5777f4fec309c761f889350 100644 (file)
 
 #include <strings.h>
 #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"
 #include "libavcodec/mpegaudiodata.h"
 #include "libavcodec/mpegaudiodecheader.h"
 #include "libavformat/avio_internal.h"
+#include "libavutil/dict.h"
 
 static int id3v1_set_string(AVFormatContext *s, const char *key,
                             uint8_t *buf, int buf_size)
 {
-    AVMetadataTag *tag;
-    if ((tag = av_metadata_get(s->metadata, key, NULL, 0)))
+    AVDictionaryEntry *tag;
+    if ((tag = av_dict_get(s->metadata, key, NULL, 0)))
         av_strlcpy(buf, tag->value, buf_size);
     return !!tag;
 }
 
 static int id3v1_create_tag(AVFormatContext *s, uint8_t *buf)
 {
-    AVMetadataTag *tag;
+    AVDictionaryEntry *tag;
     int i, count = 0;
 
     memset(buf, 0, ID3v1_TAG_SIZE); /* fail safe */
@@ -55,13 +60,13 @@ static int id3v1_create_tag(AVFormatContext *s, uint8_t *buf)
     count += id3v1_set_string(s, "TALB",    buf + 63, 30);       //album
     count += id3v1_set_string(s, "TDRL",    buf + 93,  4);       //date
     count += id3v1_set_string(s, "comment", buf + 97, 30);
-    if ((tag = av_metadata_get(s->metadata, "TRCK", NULL, 0))) { //track
+    if ((tag = av_dict_get(s->metadata, "TRCK", NULL, 0))) { //track
         buf[125] = 0;
         buf[126] = atoi(tag->value);
         count++;
     }
     buf[127] = 0xFF; /* default to unknown genre */
-    if ((tag = av_metadata_get(s->metadata, "TCON", NULL, 0))) { //genre
+    if ((tag = av_dict_get(s->metadata, "TCON", NULL, 0))) { //genre
         for(i = 0; i <= ID3v1_GENRE_MAX; i++) {
             if (!strcasecmp(tag->value, ff_id3v1_genre_str[i])) {
                 buf[127] = i;
@@ -131,51 +136,63 @@ 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,
 };
 #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 },
 };
 
@@ -186,7 +203,7 @@ static const AVClass mp3_muxer_class = {
     .version        = LIBAVUTIL_VERSION_INT,
 };
 
-static int id3v2_check_write_tag(AVFormatContext *s, AVMetadataTag *t, const char table[][4],
+static int id3v2_check_write_tag(AVFormatContext *s, AVDictionaryEntry *t, const char table[][4],
                                  enum ID3v2Encoding enc)
 {
     uint32_t tag;
@@ -345,7 +362,7 @@ static void mp3_fix_xing(AVFormatContext *s)
 static int mp3_write_header(struct AVFormatContext *s)
 {
     MP3Context  *mp3 = s->priv_data;
-    AVMetadataTag *t = NULL;
+    AVDictionaryEntry *t = NULL;
     int totlen = 0, enc = mp3->id3v2_version == 3 ? ID3v2_ENCODING_UTF16BOM :
                                                     ID3v2_ENCODING_UTF8;
     int64_t size_pos, cur_pos;
@@ -362,7 +379,7 @@ static int mp3_write_header(struct AVFormatContext *s)
     if (mp3->id3v2_version == 4)
         ff_metadata_conv(&s->metadata, ff_id3v2_4_metadata_conv, NULL);
 
-    while ((t = av_metadata_get(s->metadata, "", t, AV_METADATA_IGNORE_SUFFIX))) {
+    while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
         int ret;
 
         if ((ret = id3v2_check_write_tag(s, t, ff_id3v2_tags, enc)) > 0) {
@@ -443,17 +460,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