| OLD | NEW |
| 1 /* | 1 /* |
| 2 * ASF muxer | 2 * ASF muxer |
| 3 * Copyright (c) 2000, 2001 Fabrice Bellard | 3 * Copyright (c) 2000, 2001 Fabrice Bellard |
| 4 * | 4 * |
| 5 * This file is part of FFmpeg. | 5 * This file is part of FFmpeg. |
| 6 * | 6 * |
| 7 * FFmpeg is free software; you can redistribute it and/or | 7 * FFmpeg is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Lesser General Public | 8 * modify it under the terms of the GNU Lesser General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2.1 of the License, or (at your option) any later version. | 10 * version 2.1 of the License, or (at your option) any later version. |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 }; | 196 }; |
| 197 | 197 |
| 198 #define PREROLL_TIME 3100 | 198 #define PREROLL_TIME 3100 |
| 199 | 199 |
| 200 static void put_guid(ByteIOContext *s, const ff_asf_guid *g) | 200 static void put_guid(ByteIOContext *s, const ff_asf_guid *g) |
| 201 { | 201 { |
| 202 assert(sizeof(*g) == 16); | 202 assert(sizeof(*g) == 16); |
| 203 put_buffer(s, *g, sizeof(*g)); | 203 put_buffer(s, *g, sizeof(*g)); |
| 204 } | 204 } |
| 205 | 205 |
| 206 static void put_str16_nolen(ByteIOContext *s, const char *tag); | 206 static int put_str16_nolen(ByteIOContext *s, const char *tag) |
| 207 { |
| 208 const uint8_t *q = tag; |
| 209 int ret = 0; |
| 210 |
| 211 while (*q) { |
| 212 uint32_t ch; |
| 213 uint16_t tmp; |
| 214 |
| 215 GET_UTF8(ch, *q++, break;) |
| 216 PUT_UTF16(ch, tmp, put_le16(s, tmp);ret += 2;) |
| 217 } |
| 218 put_le16(s, 0); |
| 219 ret += 2; |
| 220 return ret; |
| 221 } |
| 222 |
| 207 static void put_str16(ByteIOContext *s, const char *tag) | 223 static void put_str16(ByteIOContext *s, const char *tag) |
| 208 { | 224 { |
| 209 put_le16(s,strlen(tag) + 1); | 225 int len; |
| 210 put_str16_nolen(s, tag); | 226 uint8_t *pb; |
| 211 } | 227 ByteIOContext *dyn_buf; |
| 228 if (url_open_dyn_buf(&dyn_buf) < 0) |
| 229 return; |
| 212 | 230 |
| 213 static void put_str16_nolen(ByteIOContext *s, const char *tag) | 231 put_str16_nolen(dyn_buf, tag); |
| 214 { | 232 len = url_close_dyn_buf(dyn_buf, &pb); |
| 215 int c; | 233 put_le16(s, len); |
| 216 | 234 put_buffer(s, pb, len); |
| 217 do{ | 235 av_freep(&pb); |
| 218 c = (uint8_t)*tag++; | |
| 219 put_le16(s, c); | |
| 220 }while(c); | |
| 221 } | 236 } |
| 222 | 237 |
| 223 static int64_t put_header(ByteIOContext *pb, const ff_asf_guid *g) | 238 static int64_t put_header(ByteIOContext *pb, const ff_asf_guid *g) |
| 224 { | 239 { |
| 225 int64_t pos; | 240 int64_t pos; |
| 226 | 241 |
| 227 pos = url_ftell(pb); | 242 pos = url_ftell(pb); |
| 228 put_guid(pb, g); | 243 put_guid(pb, g); |
| 229 put_le64(pb, 24); | 244 put_le64(pb, 24); |
| 230 return pos; | 245 return pos; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 t = ti * INT64_C(10000000); | 280 t = ti * INT64_C(10000000); |
| 266 t += INT64_C(116444736000000000); | 281 t += INT64_C(116444736000000000); |
| 267 return t; | 282 return t; |
| 268 } | 283 } |
| 269 | 284 |
| 270 /* write the header (used two times if non streamed) */ | 285 /* write the header (used two times if non streamed) */ |
| 271 static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data
_chunk_size) | 286 static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data
_chunk_size) |
| 272 { | 287 { |
| 273 ASFContext *asf = s->priv_data; | 288 ASFContext *asf = s->priv_data; |
| 274 ByteIOContext *pb = s->pb; | 289 ByteIOContext *pb = s->pb; |
| 275 AVMetadataTag *title, *author, *copyright, *comment; | 290 AVMetadataTag *tags[5]; |
| 276 int header_size, n, extra_size, extra_size2, wav_extra_size, file_time; | 291 int header_size, n, extra_size, extra_size2, wav_extra_size, file_time; |
| 277 int has_title; | 292 int has_title; |
| 278 int metadata_count; | 293 int metadata_count; |
| 279 AVCodecContext *enc; | 294 AVCodecContext *enc; |
| 280 int64_t header_offset, cur_pos, hpos; | 295 int64_t header_offset, cur_pos, hpos; |
| 281 int bit_rate; | 296 int bit_rate; |
| 282 int64_t duration; | 297 int64_t duration; |
| 283 | 298 |
| 284 title = av_metadata_get(s->metadata, "title" , NULL, 0); | 299 tags[0] = av_metadata_get(s->metadata, "title" , NULL, 0); |
| 285 author = av_metadata_get(s->metadata, "author" , NULL, 0); | 300 tags[1] = av_metadata_get(s->metadata, "author" , NULL, 0); |
| 286 copyright = av_metadata_get(s->metadata, "copyright", NULL, 0); | 301 tags[2] = av_metadata_get(s->metadata, "copyright", NULL, 0); |
| 287 comment = av_metadata_get(s->metadata, "comment" , NULL, 0); | 302 tags[3] = av_metadata_get(s->metadata, "comment" , NULL, 0); |
| 303 tags[4] = av_metadata_get(s->metadata, "rating" , NULL, 0); |
| 288 | 304 |
| 289 duration = asf->duration + PREROLL_TIME * 10000; | 305 duration = asf->duration + PREROLL_TIME * 10000; |
| 290 has_title = title || author || copyright || comment; | 306 has_title = tags[0] || tags[1] || tags[2] || tags[3] || tags[4]; |
| 291 metadata_count = s->metadata ? s->metadata->count : 0; | 307 metadata_count = s->metadata ? s->metadata->count : 0; |
| 292 | 308 |
| 293 bit_rate = 0; | 309 bit_rate = 0; |
| 294 for(n=0;n<s->nb_streams;n++) { | 310 for(n=0;n<s->nb_streams;n++) { |
| 295 enc = s->streams[n]->codec; | 311 enc = s->streams[n]->codec; |
| 296 | 312 |
| 297 av_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */ | 313 av_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */ |
| 298 | 314 |
| 299 bit_rate += enc->bit_rate; | 315 bit_rate += enc->bit_rate; |
| 300 } | 316 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 328 | 344 |
| 329 /* unknown headers */ | 345 /* unknown headers */ |
| 330 hpos = put_header(pb, &ff_asf_head1_guid); | 346 hpos = put_header(pb, &ff_asf_head1_guid); |
| 331 put_guid(pb, &ff_asf_head2_guid); | 347 put_guid(pb, &ff_asf_head2_guid); |
| 332 put_le32(pb, 6); | 348 put_le32(pb, 6); |
| 333 put_le16(pb, 0); | 349 put_le16(pb, 0); |
| 334 end_header(pb, hpos); | 350 end_header(pb, hpos); |
| 335 | 351 |
| 336 /* title and other infos */ | 352 /* title and other infos */ |
| 337 if (has_title) { | 353 if (has_title) { |
| 354 int len; |
| 355 uint8_t *buf; |
| 356 ByteIOContext *dyn_buf; |
| 357 |
| 358 if (url_open_dyn_buf(&dyn_buf) < 0) |
| 359 return AVERROR(ENOMEM); |
| 360 |
| 338 hpos = put_header(pb, &ff_asf_comment_header); | 361 hpos = put_header(pb, &ff_asf_comment_header); |
| 339 put_le16(pb, title ? 2 * (strlen(title->value ) + 1) : 0); | 362 |
| 340 put_le16(pb, author ? 2 * (strlen(author->value ) + 1) : 0); | 363 for (n = 0; n < FF_ARRAY_ELEMS(tags); n++) { |
| 341 put_le16(pb, copyright ? 2 * (strlen(copyright->value) + 1) : 0); | 364 len = tags[n] ? put_str16_nolen(dyn_buf, tags[n]->value) : 0; |
| 342 put_le16(pb, comment ? 2 * (strlen(comment->value ) + 1) : 0); | 365 put_le16(pb, len); |
| 343 put_le16(pb, 0); | 366 } |
| 344 if (title ) put_str16_nolen(pb, title->value ); | 367 len = url_close_dyn_buf(dyn_buf, &buf); |
| 345 if (author ) put_str16_nolen(pb, author->value ); | 368 put_buffer(pb, buf, len); |
| 346 if (copyright) put_str16_nolen(pb, copyright->value); | 369 av_freep(&buf); |
| 347 if (comment ) put_str16_nolen(pb, comment->value ); | |
| 348 end_header(pb, hpos); | 370 end_header(pb, hpos); |
| 349 } | 371 } |
| 350 if (metadata_count) { | 372 if (metadata_count) { |
| 351 AVMetadataTag *tag = NULL; | 373 AVMetadataTag *tag = NULL; |
| 352 hpos = put_header(pb, &ff_asf_extended_content_header); | 374 hpos = put_header(pb, &ff_asf_extended_content_header); |
| 353 put_le16(pb, metadata_count); | 375 put_le16(pb, metadata_count); |
| 354 while ((tag = av_metadata_get(s->metadata, "", tag, AV_METADATA_IGNORE_S
UFFIX))) { | 376 while ((tag = av_metadata_get(s->metadata, "", tag, AV_METADATA_IGNORE_S
UFFIX))) { |
| 355 put_le16(pb, 2*(strlen(tag->key) + 3) + 1); | 377 put_str16(pb, tag->key); |
| 356 put_le16(pb, 'W'); | |
| 357 put_le16(pb, 'M'); | |
| 358 put_le16(pb, '/'); | |
| 359 put_str16_nolen(pb, tag->key); | |
| 360 put_le16(pb, 0); | 378 put_le16(pb, 0); |
| 361 put_le16(pb, 2*strlen(tag->value) + 1); | 379 put_str16(pb, tag->value); |
| 362 put_str16_nolen(pb, tag->value); | |
| 363 } | 380 } |
| 364 end_header(pb, hpos); | 381 end_header(pb, hpos); |
| 365 } | 382 } |
| 366 | 383 |
| 367 /* stream headers */ | 384 /* stream headers */ |
| 368 for(n=0;n<s->nb_streams;n++) { | 385 for(n=0;n<s->nb_streams;n++) { |
| 369 int64_t es_pos; | 386 int64_t es_pos; |
| 370 // ASFStream *stream = &asf->streams[n]; | 387 // ASFStream *stream = &asf->streams[n]; |
| 371 | 388 |
| 372 enc = s->streams[n]->codec; | 389 enc = s->streams[n]->codec; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 end_header(pb, hpos); | 459 end_header(pb, hpos); |
| 443 } | 460 } |
| 444 | 461 |
| 445 /* media comments */ | 462 /* media comments */ |
| 446 | 463 |
| 447 hpos = put_header(pb, &ff_asf_codec_comment_header); | 464 hpos = put_header(pb, &ff_asf_codec_comment_header); |
| 448 put_guid(pb, &ff_asf_codec_comment1_header); | 465 put_guid(pb, &ff_asf_codec_comment1_header); |
| 449 put_le32(pb, s->nb_streams); | 466 put_le32(pb, s->nb_streams); |
| 450 for(n=0;n<s->nb_streams;n++) { | 467 for(n=0;n<s->nb_streams;n++) { |
| 451 AVCodec *p; | 468 AVCodec *p; |
| 469 const char *desc; |
| 470 int len; |
| 471 uint8_t *buf; |
| 472 ByteIOContext *dyn_buf; |
| 452 | 473 |
| 453 enc = s->streams[n]->codec; | 474 enc = s->streams[n]->codec; |
| 454 p = avcodec_find_encoder(enc->codec_id); | 475 p = avcodec_find_encoder(enc->codec_id); |
| 455 | 476 |
| 456 if(enc->codec_type == CODEC_TYPE_AUDIO) | 477 if(enc->codec_type == CODEC_TYPE_AUDIO) |
| 457 put_le16(pb, 2); | 478 put_le16(pb, 2); |
| 458 else if(enc->codec_type == CODEC_TYPE_VIDEO) | 479 else if(enc->codec_type == CODEC_TYPE_VIDEO) |
| 459 put_le16(pb, 1); | 480 put_le16(pb, 1); |
| 460 else | 481 else |
| 461 put_le16(pb, -1); | 482 put_le16(pb, -1); |
| 462 | 483 |
| 463 if(enc->codec_id == CODEC_ID_WMAV2) | 484 if(enc->codec_id == CODEC_ID_WMAV2) |
| 464 put_str16(pb, "Windows Media Audio V8"); | 485 desc = "Windows Media Audio V8"; |
| 465 else | 486 else |
| 466 put_str16(pb, p ? p->name : enc->codec_name); | 487 desc = p ? p->name : enc->codec_name; |
| 488 |
| 489 if ( url_open_dyn_buf(&dyn_buf) < 0) |
| 490 return AVERROR(ENOMEM); |
| 491 |
| 492 put_str16_nolen(dyn_buf, desc); |
| 493 len = url_close_dyn_buf(dyn_buf, &buf); |
| 494 put_le16(pb, len / 2); // "number of characters" = length in bytes / 2 |
| 495 |
| 496 put_buffer(pb, buf, len); |
| 497 av_freep(&buf); |
| 498 |
| 467 put_le16(pb, 0); /* no parameters */ | 499 put_le16(pb, 0); /* no parameters */ |
| 468 | 500 |
| 469 | 501 |
| 470 /* id */ | 502 /* id */ |
| 471 if (enc->codec_type == CODEC_TYPE_AUDIO) { | 503 if (enc->codec_type == CODEC_TYPE_AUDIO) { |
| 472 put_le16(pb, 2); | 504 put_le16(pb, 2); |
| 473 put_le16(pb, enc->codec_tag); | 505 put_le16(pb, enc->codec_tag); |
| 474 } else { | 506 } else { |
| 475 put_le16(pb, 4); | 507 put_le16(pb, 4); |
| 476 put_le32(pb, enc->codec_tag); | 508 put_le32(pb, enc->codec_tag); |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 873 #endif | 905 #endif |
| 874 CODEC_ID_MSMPEG4V3, | 906 CODEC_ID_MSMPEG4V3, |
| 875 asf_write_stream_header, | 907 asf_write_stream_header, |
| 876 asf_write_packet, | 908 asf_write_packet, |
| 877 asf_write_trailer, | 909 asf_write_trailer, |
| 878 .flags = AVFMT_GLOBALHEADER, | 910 .flags = AVFMT_GLOBALHEADER, |
| 879 .codec_tag= (const AVCodecTag* const []){codec_asf_bmp_tags, ff_codec_bmp_ta
gs, ff_codec_wav_tags, 0}, | 911 .codec_tag= (const AVCodecTag* const []){codec_asf_bmp_tags, ff_codec_bmp_ta
gs, ff_codec_wav_tags, 0}, |
| 880 .metadata_conv = ff_asf_metadata_conv, | 912 .metadata_conv = ff_asf_metadata_conv, |
| 881 }; | 913 }; |
| 882 #endif //CONFIG_ASF_STREAM_MUXER | 914 #endif //CONFIG_ASF_STREAM_MUXER |
| OLD | NEW |