1/* 2 * MP3 muxer 3 * Copyright (c) 2003 Fabrice Bellard 4 * 5 * This file is part of Libav. 6 * 7 * Libav is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * Libav is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with Libav; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include "avformat.h" 23#include "avio_internal.h" 24#include "id3v1.h" 25#include "id3v2.h" 26#include "rawenc.h" 27#include "libavutil/avstring.h" 28#include "libavcodec/mpegaudio.h" 29#include "libavcodec/mpegaudiodata.h" 30#include "libavcodec/mpegaudiodecheader.h" 31#include "libavutil/intreadwrite.h" 32#include "libavutil/opt.h" 33#include "libavutil/dict.h" 34 35static int id3v1_set_string(AVFormatContext *s, const char *key, 36 uint8_t *buf, int buf_size) 37{ 38 AVDictionaryEntry *tag; 39 if ((tag = av_dict_get(s->metadata, key, NULL, 0))) 40 av_strlcpy(buf, tag->value, buf_size); 41 return !!tag; 42} 43 44static int id3v1_create_tag(AVFormatContext *s, uint8_t *buf) 45{ 46 AVDictionaryEntry *tag; 47 int i, count = 0; 48 49 memset(buf, 0, ID3v1_TAG_SIZE); /* fail safe */ 50 buf[0] = 'T'; 51 buf[1] = 'A'; 52 buf[2] = 'G'; 53 count += id3v1_set_string(s, "TIT2", buf + 3, 30); //title 54 count += id3v1_set_string(s, "TPE1", buf + 33, 30); //author|artist 55 count += id3v1_set_string(s, "TALB", buf + 63, 30); //album 56 count += id3v1_set_string(s, "TDRL", buf + 93, 4); //date 57 count += id3v1_set_string(s, "comment", buf + 97, 30); 58 if ((tag = av_dict_get(s->metadata, "TRCK", NULL, 0))) { //track 59 buf[125] = 0; 60 buf[126] = atoi(tag->value); 61 count++; 62 } 63 buf[127] = 0xFF; /* default to unknown genre */ 64 if ((tag = av_dict_get(s->metadata, "TCON", NULL, 0))) { //genre 65 for(i = 0; i <= ID3v1_GENRE_MAX; i++) { 66 if (!av_strcasecmp(tag->value, ff_id3v1_genre_str[i])) { 67 buf[127] = i; 68 count++; 69 break; 70 } 71 } 72 } 73 return count; 74} 75 76typedef struct MP3Context { 77 const AVClass *class; 78 int id3v2_version; 79 int write_id3v1; 80 int64_t nb_frames_offset; 81} MP3Context; 82 83static int mp3_write_trailer(struct AVFormatContext *s) 84{ 85 uint8_t buf[ID3v1_TAG_SIZE]; 86 MP3Context *mp3 = s->priv_data; 87 88 /* write the id3v1 tag */ 89 if (mp3 && mp3->write_id3v1 && id3v1_create_tag(s, buf) > 0) { 90 avio_write(s->pb, buf, ID3v1_TAG_SIZE); 91 } 92 93 /* write number of frames */ 94 if (mp3 && mp3->nb_frames_offset) { 95 avio_seek(s->pb, mp3->nb_frames_offset, SEEK_SET); 96 avio_wb32(s->pb, s->streams[0]->nb_frames); 97 avio_seek(s->pb, 0, SEEK_END); 98 } 99 100 avio_flush(s->pb); 101 102 return 0; 103} 104 105#if CONFIG_MP2_MUXER 106AVOutputFormat ff_mp2_muxer = { 107 .name = "mp2", 108 .long_name = NULL_IF_CONFIG_SMALL("MPEG audio layer 2"), 109 .mime_type = "audio/x-mpeg", 110 .extensions = "mp2,m2a", 111 .audio_codec = CODEC_ID_MP2, 112 .video_codec = CODEC_ID_NONE, 113 .write_packet = ff_raw_write_packet, 114 .write_trailer = mp3_write_trailer, 115}; 116#endif 117 118#if CONFIG_MP3_MUXER 119 120static const AVOption options[] = { 121 { "id3v2_version", "Select ID3v2 version to write. Currently 3 and 4 are supported.", 122 offsetof(MP3Context, id3v2_version), AV_OPT_TYPE_INT, {.dbl = 4}, 3, 4, AV_OPT_FLAG_ENCODING_PARAM}, 123 { "write_id3v1", "Enable ID3v1 writing. ID3v1 tags are written in UTF-8 which may not be supported by most software.", 124 offsetof(MP3Context, write_id3v1), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, 125 { NULL }, 126}; 127 128static const AVClass mp3_muxer_class = { 129 .class_name = "MP3 muxer", 130 .item_name = av_default_item_name, 131 .option = options, 132 .version = LIBAVUTIL_VERSION_INT, 133}; 134 135/* insert a dummy frame containing number of frames */ 136static void mp3_write_xing(AVFormatContext *s) 137{ 138 AVCodecContext *codec = s->streams[0]->codec; 139 MP3Context *mp3 = s->priv_data; 140 int bitrate_idx = 1; // 32 kbps 141 int64_t xing_offset = (codec->channels == 2) ? 32 : 17; 142 int32_t header; 143 MPADecodeHeader mpah; 144 int srate_idx, i, channels; 145 146 for (i = 0; i < FF_ARRAY_ELEMS(avpriv_mpa_freq_tab); i++) 147 if (avpriv_mpa_freq_tab[i] == codec->sample_rate) { 148 srate_idx = i; 149 break; 150 } 151 if (i == FF_ARRAY_ELEMS(avpriv_mpa_freq_tab)) { 152 av_log(s, AV_LOG_ERROR, "Unsupported sample rate.\n"); 153 return; 154 } 155 156 switch (codec->channels) { 157 case 1: channels = MPA_MONO; break; 158 case 2: channels = MPA_STEREO; break; 159 default: av_log(s, AV_LOG_ERROR, "Unsupported number of channels.\n"); return; 160 } 161 162 /* dummy MPEG audio header */ 163 header = 0xff << 24; // sync 164 header |= (0x7 << 5 | 0x3 << 3 | 0x1 << 1 | 0x1) << 16; // sync/mpeg-1/layer 3/no crc*/ 165 header |= (bitrate_idx << 4 | srate_idx << 2) << 8; 166 header |= channels << 6; 167 avio_wb32(s->pb, header); 168 169 avpriv_mpegaudio_decode_header(&mpah, header); 170 171 ffio_fill(s->pb, 0, xing_offset); 172 ffio_wfourcc(s->pb, "Xing"); 173 avio_wb32(s->pb, 0x1); // only number of frames 174 mp3->nb_frames_offset = avio_tell(s->pb); 175 avio_wb32(s->pb, 0); 176 177 mpah.frame_size -= 4 + xing_offset + 4 + 4 + 4; 178 ffio_fill(s->pb, 0, mpah.frame_size); 179} 180 181/** 182 * Write an ID3v2 header at beginning of stream 183 */ 184 185static int mp3_write_header(struct AVFormatContext *s) 186{ 187 MP3Context *mp3 = s->priv_data; 188 int ret; 189 190 ret = ff_id3v2_write(s, mp3->id3v2_version, ID3v2_DEFAULT_MAGIC); 191 if (ret < 0) 192 return ret; 193 194 if (s->pb->seekable) 195 mp3_write_xing(s); 196 197 return 0; 198} 199 200AVOutputFormat ff_mp3_muxer = { 201 .name = "mp3", 202 .long_name = NULL_IF_CONFIG_SMALL("MPEG audio layer 3"), 203 .mime_type = "audio/x-mpeg", 204 .extensions = "mp3", 205 .priv_data_size = sizeof(MP3Context), 206 .audio_codec = CODEC_ID_MP3, 207 .video_codec = CODEC_ID_NONE, 208 .write_header = mp3_write_header, 209 .write_packet = ff_raw_write_packet, 210 .write_trailer = mp3_write_trailer, 211 .flags = AVFMT_NOTIMESTAMPS, 212 .priv_class = &mp3_muxer_class, 213}; 214#endif 215