Browse code

id3v2enc: chapter support

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2013/05/06 09:14:05
Showing 1 changed files
... ...
@@ -162,33 +162,31 @@ void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version,
162 162
     avio_wb32(pb, 0);
163 163
 }
164 164
 
165
-int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3)
165
+static int write_metadata(AVIOContext *pb, AVDictionary **metadata,
166
+                          ID3v2EncContext *id3, int enc)
166 167
 {
167 168
     AVDictionaryEntry *t = NULL;
168
-    int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM :
169
-                                  ID3v2_ENCODING_UTF8;
169
+    int ret;
170 170
 
171
-    ff_metadata_conv(&s->metadata, ff_id3v2_34_metadata_conv, NULL);
171
+    ff_metadata_conv(metadata, ff_id3v2_34_metadata_conv, NULL);
172 172
     if (id3->version == 3)
173
-        id3v2_3_metadata_split_date(&s->metadata);
173
+        id3v2_3_metadata_split_date(metadata);
174 174
     else if (id3->version == 4)
175
-        ff_metadata_conv(&s->metadata, ff_id3v2_4_metadata_conv, NULL);
176
-
177
-    while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
178
-        int ret;
175
+        ff_metadata_conv(metadata, ff_id3v2_4_metadata_conv, NULL);
179 176
 
180
-        if ((ret = id3v2_check_write_tag(id3, s->pb, t, ff_id3v2_tags, enc)) > 0) {
177
+    while ((t = av_dict_get(*metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
178
+        if ((ret = id3v2_check_write_tag(id3, pb, t, ff_id3v2_tags, enc)) > 0) {
181 179
             id3->len += ret;
182 180
             continue;
183 181
         }
184
-        if ((ret = id3v2_check_write_tag(id3, s->pb, t, id3->version == 3 ?
185
-                                               ff_id3v2_3_tags : ff_id3v2_4_tags, enc)) > 0) {
182
+        if ((ret = id3v2_check_write_tag(id3, pb, t, id3->version == 3 ?
183
+                                         ff_id3v2_3_tags : ff_id3v2_4_tags, enc)) > 0) {
186 184
             id3->len += ret;
187 185
             continue;
188 186
         }
189 187
 
190 188
         /* unknown tag, write as TXXX frame */
191
-        if ((ret = id3v2_put_ttag(id3, s->pb, t->key, t->value, MKBETAG('T', 'X', 'X', 'X'), enc)) < 0)
189
+        if ((ret = id3v2_put_ttag(id3, pb, t->key, t->value, MKBETAG('T', 'X', 'X', 'X'), enc)) < 0)
192 190
             return ret;
193 191
         id3->len += ret;
194 192
     }
... ...
@@ -196,6 +194,64 @@ int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3)
196 196
     return 0;
197 197
 }
198 198
 
199
+static int write_chapter(AVFormatContext *s, ID3v2EncContext *id3, int id, int enc)
200
+{
201
+    const AVRational time_base = {1, 1000};
202
+    AVChapter *ch = s->chapters[id];
203
+    uint8_t *dyn_buf = NULL;
204
+    AVIOContext *dyn_bc = NULL;
205
+    char name[123];
206
+    int len, start, end, ret;
207
+
208
+    if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0)
209
+        goto fail;
210
+
211
+    start = av_rescale_q(ch->start, ch->time_base, time_base);
212
+    end   = av_rescale_q(ch->end,   ch->time_base, time_base);
213
+
214
+    snprintf(name, 122, "ch%d", id);
215
+    id3->len += avio_put_str(dyn_bc, name);
216
+    avio_wb32(dyn_bc, start);
217
+    avio_wb32(dyn_bc, end);
218
+    avio_wb32(dyn_bc, 0xFFFFFFFFu);
219
+    avio_wb32(dyn_bc, 0xFFFFFFFFu);
220
+
221
+    if ((ret = write_metadata(dyn_bc, &ch->metadata, id3, enc)) < 0)
222
+        goto fail;
223
+
224
+    len = avio_close_dyn_buf(dyn_bc, &dyn_buf);
225
+    id3->len += 16 + ID3v2_HEADER_SIZE;
226
+
227
+    avio_wb32(s->pb, MKBETAG('C', 'H', 'A', 'P'));
228
+    avio_wb32(s->pb, len);
229
+    avio_wb16(s->pb, 0);
230
+    avio_write(s->pb, dyn_buf, len);
231
+
232
+fail:
233
+    if (dyn_bc && !dyn_buf)
234
+        avio_close_dyn_buf(dyn_bc, &dyn_buf);
235
+    av_freep(&dyn_buf);
236
+
237
+    return ret;
238
+}
239
+
240
+int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3)
241
+{
242
+    int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM :
243
+                                  ID3v2_ENCODING_UTF8;
244
+    int i, ret;
245
+
246
+    if ((ret = write_metadata(s->pb, &s->metadata, id3, enc)) < 0)
247
+        return ret;
248
+
249
+    for (i = 0; i < s->nb_chapters; i++) {
250
+        if ((ret = write_chapter(s, id3, i, enc)) < 0)
251
+            return ret;
252
+    }
253
+
254
+    return 0;
255
+}
256
+
199 257
 int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt)
200 258
 {
201 259
     AVStream *st = s->streams[pkt->stream_index];