1/* 2 * ASF muxer 3 * Copyright (c) 2000, 2001 Fabrice Bellard 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21#include "avformat.h" 22#include "metadata.h" 23#include "riff.h" 24#include "asf.h" 25 26#undef NDEBUG 27#include <assert.h> 28 29 30#define ASF_INDEXED_INTERVAL 10000000 31#define ASF_INDEX_BLOCK 600 32 33#define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2 34#define ASF_PACKET_ERROR_CORRECTION_FLAGS (\ 35 ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT | \ 36 ASF_PACKET_ERROR_CORRECTION_DATA_SIZE\ 37 ) 38 39#if (ASF_PACKET_ERROR_CORRECTION_FLAGS != 0) 40# define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 1 41#else 42# define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 0 43#endif 44 45#define ASF_PPI_PROPERTY_FLAGS (\ 46 ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE | \ 47 ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD | \ 48 ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE | \ 49 ASF_PL_FLAG_STREAM_NUMBER_LENGTH_FIELD_IS_BYTE \ 50 ) 51 52#define ASF_PPI_LENGTH_TYPE_FLAGS 0 53 54#define ASF_PAYLOAD_FLAGS ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD 55 56#if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE)) 57# define ASF_PPI_SEQUENCE_FIELD_SIZE 1 58#endif 59#if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE)) 60# define ASF_PPI_SEQUENCE_FIELD_SIZE 2 61#endif 62#if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE)) 63# define ASF_PPI_SEQUENCE_FIELD_SIZE 4 64#endif 65#ifndef ASF_PPI_SEQUENCE_FIELD_SIZE 66# define ASF_PPI_SEQUENCE_FIELD_SIZE 0 67#endif 68 69 70#if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE)) 71# define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 1 72#endif 73#if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE)) 74# define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 2 75#endif 76#if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE)) 77# define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 4 78#endif 79#ifndef ASF_PPI_PACKET_LENGTH_FIELD_SIZE 80# define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 0 81#endif 82 83#if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE)) 84# define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 1 85#endif 86#if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE)) 87# define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 2 88#endif 89#if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE)) 90# define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 4 91#endif 92#ifndef ASF_PPI_PADDING_LENGTH_FIELD_SIZE 93# define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 0 94#endif 95 96#if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE)) 97# define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 1 98#endif 99#if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE)) 100# define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 2 101#endif 102#if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE)) 103# define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 4 104#endif 105#ifndef ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 106# define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 0 107#endif 108 109#if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE)) 110# define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 1 111#endif 112#if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE)) 113# define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 2 114#endif 115#if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE)) 116# define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 4 117#endif 118#ifndef ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 119# define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 0 120#endif 121 122#if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE)) 123# define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 1 124#endif 125#if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE)) 126# define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 2 127#endif 128#if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE)) 129# define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 4 130#endif 131#ifndef ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 132# define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 0 133#endif 134 135#if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_BYTE == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE)) 136# define ASF_PAYLOAD_LENGTH_FIELD_SIZE 1 137#endif 138#if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE)) 139# define ASF_PAYLOAD_LENGTH_FIELD_SIZE 2 140#endif 141#ifndef ASF_PAYLOAD_LENGTH_FIELD_SIZE 142# define ASF_PAYLOAD_LENGTH_FIELD_SIZE 0 143#endif 144 145#define PACKET_HEADER_MIN_SIZE (\ 146 ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE + \ 147 ASF_PACKET_ERROR_CORRECTION_DATA_SIZE + \ 148 1 + /*Length Type Flags*/ \ 149 1 + /*Property Flags*/ \ 150 ASF_PPI_PACKET_LENGTH_FIELD_SIZE + \ 151 ASF_PPI_SEQUENCE_FIELD_SIZE + \ 152 ASF_PPI_PADDING_LENGTH_FIELD_SIZE + \ 153 4 + /*Send Time Field*/ \ 154 2 /*Duration Field*/ \ 155 ) 156 157 158// Replicated Data shall be at least 8 bytes long. 159#define ASF_PAYLOAD_REPLICATED_DATA_LENGTH 0x08 160 161#define PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD (\ 162 1 + /*Stream Number*/ \ 163 ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \ 164 ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \ 165 ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \ 166 ASF_PAYLOAD_REPLICATED_DATA_LENGTH \ 167 ) 168 169#define PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS (\ 170 1 + /*Stream Number*/ \ 171 ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \ 172 ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \ 173 ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \ 174 ASF_PAYLOAD_REPLICATED_DATA_LENGTH + \ 175 ASF_PAYLOAD_LENGTH_FIELD_SIZE \ 176 ) 177 178#define SINGLE_PAYLOAD_DATA_LENGTH (\ 179 PACKET_SIZE - \ 180 PACKET_HEADER_MIN_SIZE - \ 181 PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD \ 182 ) 183 184#define MULTI_PAYLOAD_CONSTANT (\ 185 PACKET_SIZE - \ 186 PACKET_HEADER_MIN_SIZE - \ 187 1 - /*Payload Flags*/ \ 188 2*PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS \ 189 ) 190 191static const AVCodecTag codec_asf_bmp_tags[] = { 192 { CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') }, 193 { CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') }, 194 { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') }, 195 { CODEC_ID_NONE, 0 }, 196}; 197 198#define PREROLL_TIME 3100 199 200static void put_guid(ByteIOContext *s, const ff_asf_guid *g) 201{ 202 assert(sizeof(*g) == 16); 203 put_buffer(s, *g, sizeof(*g)); 204} 205 206static void put_str16(ByteIOContext *s, const char *tag) 207{ 208 int len; 209 uint8_t *pb; 210 ByteIOContext *dyn_buf; 211 if (url_open_dyn_buf(&dyn_buf) < 0) 212 return; 213 214 ff_put_str16_nolen(dyn_buf, tag); 215 len = url_close_dyn_buf(dyn_buf, &pb); 216 put_le16(s, len); 217 put_buffer(s, pb, len); 218 av_freep(&pb); 219} 220 221static int64_t put_header(ByteIOContext *pb, const ff_asf_guid *g) 222{ 223 int64_t pos; 224 225 pos = url_ftell(pb); 226 put_guid(pb, g); 227 put_le64(pb, 24); 228 return pos; 229} 230 231/* update header size */ 232static void end_header(ByteIOContext *pb, int64_t pos) 233{ 234 int64_t pos1; 235 236 pos1 = url_ftell(pb); 237 url_fseek(pb, pos + 16, SEEK_SET); 238 put_le64(pb, pos1 - pos); 239 url_fseek(pb, pos1, SEEK_SET); 240} 241 242/* write an asf chunk (only used in streaming case) */ 243static void put_chunk(AVFormatContext *s, int type, int payload_length, int flags) 244{ 245 ASFContext *asf = s->priv_data; 246 ByteIOContext *pb = s->pb; 247 int length; 248 249 length = payload_length + 8; 250 put_le16(pb, type); 251 put_le16(pb, length); //size 252 put_le32(pb, asf->seqno);//sequence number 253 put_le16(pb, flags); /* unknown bytes */ 254 put_le16(pb, length); //size_confirm 255 asf->seqno++; 256} 257 258/* convert from unix to windows time */ 259static int64_t unix_to_file_time(int ti) 260{ 261 int64_t t; 262 263 t = ti * INT64_C(10000000); 264 t += INT64_C(116444736000000000); 265 return t; 266} 267 268/* write the header (used two times if non streamed) */ 269static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data_chunk_size) 270{ 271 ASFContext *asf = s->priv_data; 272 ByteIOContext *pb = s->pb; 273 AVMetadataTag *tags[5]; 274 int header_size, n, extra_size, extra_size2, wav_extra_size, file_time; 275 int has_title; 276 int metadata_count; 277 AVCodecContext *enc; 278 int64_t header_offset, cur_pos, hpos; 279 int bit_rate; 280 int64_t duration; 281 282 tags[0] = av_metadata_get(s->metadata, "title" , NULL, 0); 283 tags[1] = av_metadata_get(s->metadata, "author" , NULL, 0); 284 tags[2] = av_metadata_get(s->metadata, "copyright", NULL, 0); 285 tags[3] = av_metadata_get(s->metadata, "comment" , NULL, 0); 286 tags[4] = av_metadata_get(s->metadata, "rating" , NULL, 0); 287 288 duration = asf->duration + PREROLL_TIME * 10000; 289 has_title = tags[0] || tags[1] || tags[2] || tags[3] || tags[4]; 290 metadata_count = s->metadata ? s->metadata->count : 0; 291 292 bit_rate = 0; 293 for(n=0;n<s->nb_streams;n++) { 294 enc = s->streams[n]->codec; 295 296 av_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */ 297 298 bit_rate += enc->bit_rate; 299 } 300 301 if (asf->is_streamed) { 302 put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */ 303 } 304 305 put_guid(pb, &ff_asf_header); 306 put_le64(pb, -1); /* header length, will be patched after */ 307 put_le32(pb, 3 + has_title + !!metadata_count + s->nb_streams); /* number of chunks in header */ 308 put_byte(pb, 1); /* ??? */ 309 put_byte(pb, 2); /* ??? */ 310 311 /* file header */ 312 header_offset = url_ftell(pb); 313 hpos = put_header(pb, &ff_asf_file_header); 314 put_guid(pb, &ff_asf_my_guid); 315 put_le64(pb, file_size); 316 file_time = 0; 317 put_le64(pb, unix_to_file_time(file_time)); 318 put_le64(pb, asf->nb_packets); /* number of packets */ 319 put_le64(pb, duration); /* end time stamp (in 100ns units) */ 320 put_le64(pb, asf->duration); /* duration (in 100ns units) */ 321 put_le64(pb, PREROLL_TIME); /* start time stamp */ 322 put_le32(pb, (asf->is_streamed || url_is_streamed(pb)) ? 3 : 2); /* ??? */ 323 put_le32(pb, s->packet_size); /* packet size */ 324 put_le32(pb, s->packet_size); /* packet size */ 325 put_le32(pb, bit_rate); /* Nominal data rate in bps */ 326 end_header(pb, hpos); 327 328 /* unknown headers */ 329 hpos = put_header(pb, &ff_asf_head1_guid); 330 put_guid(pb, &ff_asf_head2_guid); 331 put_le32(pb, 6); 332 put_le16(pb, 0); 333 end_header(pb, hpos); 334 335 /* title and other infos */ 336 if (has_title) { 337 int len; 338 uint8_t *buf; 339 ByteIOContext *dyn_buf; 340 341 if (url_open_dyn_buf(&dyn_buf) < 0) 342 return AVERROR(ENOMEM); 343 344 hpos = put_header(pb, &ff_asf_comment_header); 345 346 for (n = 0; n < FF_ARRAY_ELEMS(tags); n++) { 347 len = tags[n] ? ff_put_str16_nolen(dyn_buf, tags[n]->value) : 0; 348 put_le16(pb, len); 349 } 350 len = url_close_dyn_buf(dyn_buf, &buf); 351 put_buffer(pb, buf, len); 352 av_freep(&buf); 353 end_header(pb, hpos); 354 } 355 if (metadata_count) { 356 AVMetadataTag *tag = NULL; 357 hpos = put_header(pb, &ff_asf_extended_content_header); 358 put_le16(pb, metadata_count); 359 while ((tag = av_metadata_get(s->metadata, "", tag, AV_METADATA_IGNORE_SUFFIX))) { 360 put_str16(pb, tag->key); 361 put_le16(pb, 0); 362 put_str16(pb, tag->value); 363 } 364 end_header(pb, hpos); 365 } 366 367 /* stream headers */ 368 for(n=0;n<s->nb_streams;n++) { 369 int64_t es_pos; 370 // ASFStream *stream = &asf->streams[n]; 371 372 enc = s->streams[n]->codec; 373 asf->streams[n].num = n + 1; 374 asf->streams[n].seq = 0; 375 376 377 switch(enc->codec_type) { 378 case AVMEDIA_TYPE_AUDIO: 379 wav_extra_size = 0; 380 extra_size = 18 + wav_extra_size; 381 extra_size2 = 8; 382 break; 383 default: 384 case AVMEDIA_TYPE_VIDEO: 385 wav_extra_size = enc->extradata_size; 386 extra_size = 0x33 + wav_extra_size; 387 extra_size2 = 0; 388 break; 389 } 390 391 hpos = put_header(pb, &ff_asf_stream_header); 392 if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { 393 put_guid(pb, &ff_asf_audio_stream); 394 put_guid(pb, &ff_asf_audio_conceal_spread); 395 } else { 396 put_guid(pb, &ff_asf_video_stream); 397 put_guid(pb, &ff_asf_video_conceal_none); 398 } 399 put_le64(pb, 0); /* ??? */ 400 es_pos = url_ftell(pb); 401 put_le32(pb, extra_size); /* wav header len */ 402 put_le32(pb, extra_size2); /* additional data len */ 403 put_le16(pb, n + 1); /* stream number */ 404 put_le32(pb, 0); /* ??? */ 405 406 if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { 407 /* WAVEFORMATEX header */ 408 int wavsize = ff_put_wav_header(pb, enc); 409 if ((enc->codec_id != CODEC_ID_MP3) && (enc->codec_id != CODEC_ID_MP2) && (enc->codec_id != CODEC_ID_ADPCM_IMA_WAV) && (enc->extradata_size==0)) { 410 wavsize += 2; 411 put_le16(pb, 0); 412 } 413 414 if (wavsize < 0) 415 return -1; 416 if (wavsize != extra_size) { 417 cur_pos = url_ftell(pb); 418 url_fseek(pb, es_pos, SEEK_SET); 419 put_le32(pb, wavsize); /* wav header len */ 420 url_fseek(pb, cur_pos, SEEK_SET); 421 } 422 /* ERROR Correction */ 423 put_byte(pb, 0x01); 424 if(enc->codec_id == CODEC_ID_ADPCM_G726 || !enc->block_align){ 425 put_le16(pb, 0x0190); 426 put_le16(pb, 0x0190); 427 }else{ 428 put_le16(pb, enc->block_align); 429 put_le16(pb, enc->block_align); 430 } 431 put_le16(pb, 0x01); 432 put_byte(pb, 0x00); 433 } else { 434 put_le32(pb, enc->width); 435 put_le32(pb, enc->height); 436 put_byte(pb, 2); /* ??? */ 437 put_le16(pb, 40 + enc->extradata_size); /* size */ 438 439 /* BITMAPINFOHEADER header */ 440 ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 1); 441 } 442 end_header(pb, hpos); 443 } 444 445 /* media comments */ 446 447 hpos = put_header(pb, &ff_asf_codec_comment_header); 448 put_guid(pb, &ff_asf_codec_comment1_header); 449 put_le32(pb, s->nb_streams); 450 for(n=0;n<s->nb_streams;n++) { 451 AVCodec *p; 452 const char *desc; 453 int len; 454 uint8_t *buf; 455 ByteIOContext *dyn_buf; 456 457 enc = s->streams[n]->codec; 458 p = avcodec_find_encoder(enc->codec_id); 459 460 if(enc->codec_type == AVMEDIA_TYPE_AUDIO) 461 put_le16(pb, 2); 462 else if(enc->codec_type == AVMEDIA_TYPE_VIDEO) 463 put_le16(pb, 1); 464 else 465 put_le16(pb, -1); 466 467 if(enc->codec_id == CODEC_ID_WMAV2) 468 desc = "Windows Media Audio V8"; 469 else 470 desc = p ? p->name : enc->codec_name; 471 472 if ( url_open_dyn_buf(&dyn_buf) < 0) 473 return AVERROR(ENOMEM); 474 475 ff_put_str16_nolen(dyn_buf, desc); 476 len = url_close_dyn_buf(dyn_buf, &buf); 477 put_le16(pb, len / 2); // "number of characters" = length in bytes / 2 478 479 put_buffer(pb, buf, len); 480 av_freep(&buf); 481 482 put_le16(pb, 0); /* no parameters */ 483 484 485 /* id */ 486 if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { 487 put_le16(pb, 2); 488 put_le16(pb, enc->codec_tag); 489 } else { 490 put_le16(pb, 4); 491 put_le32(pb, enc->codec_tag); 492 } 493 if(!enc->codec_tag) 494 return -1; 495 } 496 end_header(pb, hpos); 497 498 /* patch the header size fields */ 499 500 cur_pos = url_ftell(pb); 501 header_size = cur_pos - header_offset; 502 if (asf->is_streamed) { 503 header_size += 8 + 30 + 50; 504 505 url_fseek(pb, header_offset - 10 - 30, SEEK_SET); 506 put_le16(pb, header_size); 507 url_fseek(pb, header_offset - 2 - 30, SEEK_SET); 508 put_le16(pb, header_size); 509 510 header_size -= 8 + 30 + 50; 511 } 512 header_size += 24 + 6; 513 url_fseek(pb, header_offset - 14, SEEK_SET); 514 put_le64(pb, header_size); 515 url_fseek(pb, cur_pos, SEEK_SET); 516 517 /* movie chunk, followed by packets of packet_size */ 518 asf->data_offset = cur_pos; 519 put_guid(pb, &ff_asf_data_header); 520 put_le64(pb, data_chunk_size); 521 put_guid(pb, &ff_asf_my_guid); 522 put_le64(pb, asf->nb_packets); /* nb packets */ 523 put_byte(pb, 1); /* ??? */ 524 put_byte(pb, 1); /* ??? */ 525 return 0; 526} 527 528static int asf_write_header(AVFormatContext *s) 529{ 530 ASFContext *asf = s->priv_data; 531 532 s->packet_size = PACKET_SIZE; 533 asf->nb_packets = 0; 534 535 asf->last_indexed_pts = 0; 536 asf->index_ptr = av_malloc( sizeof(ASFIndex) * ASF_INDEX_BLOCK ); 537 asf->nb_index_memory_alloc = ASF_INDEX_BLOCK; 538 asf->nb_index_count = 0; 539 asf->maximum_packet = 0; 540 541 /* the data-chunk-size has to be 50, which is data_size - asf->data_offset 542 * at the moment this function is done. It is needed to use asf as 543 * streamable format. */ 544 if (asf_write_header1(s, 0, 50) < 0) { 545 //av_free(asf); 546 return -1; 547 } 548 549 put_flush_packet(s->pb); 550 551 asf->packet_nb_payloads = 0; 552 asf->packet_timestamp_start = -1; 553 asf->packet_timestamp_end = -1; 554 init_put_byte(&asf->pb, asf->packet_buf, s->packet_size, 1, 555 NULL, NULL, NULL, NULL); 556 557 return 0; 558} 559 560static int asf_write_stream_header(AVFormatContext *s) 561{ 562 ASFContext *asf = s->priv_data; 563 564 asf->is_streamed = 1; 565 566 return asf_write_header(s); 567} 568 569static int put_payload_parsing_info( 570 AVFormatContext *s, 571 unsigned int sendtime, 572 unsigned int duration, 573 int nb_payloads, 574 int padsize 575 ) 576{ 577 ASFContext *asf = s->priv_data; 578 ByteIOContext *pb = s->pb; 579 int ppi_size, i; 580 int64_t start= url_ftell(pb); 581 582 int iLengthTypeFlags = ASF_PPI_LENGTH_TYPE_FLAGS; 583 584 padsize -= PACKET_HEADER_MIN_SIZE; 585 if(asf->multi_payloads_present) 586 padsize--; 587 assert(padsize>=0); 588 589 put_byte(pb, ASF_PACKET_ERROR_CORRECTION_FLAGS); 590 for (i = 0; i < ASF_PACKET_ERROR_CORRECTION_DATA_SIZE; i++){ 591 put_byte(pb, 0x0); 592 } 593 594 if (asf->multi_payloads_present) 595 iLengthTypeFlags |= ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT; 596 597 if (padsize > 0) { 598 if (padsize < 256) 599 iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE; 600 else 601 iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD; 602 } 603 put_byte(pb, iLengthTypeFlags); 604 605 put_byte(pb, ASF_PPI_PROPERTY_FLAGS); 606 607 if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD) 608 put_le16(pb, padsize - 2); 609 if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE) 610 put_byte(pb, padsize - 1); 611 612 put_le32(pb, sendtime); 613 put_le16(pb, duration); 614 if (asf->multi_payloads_present) 615 put_byte(pb, nb_payloads | ASF_PAYLOAD_FLAGS); 616 617 ppi_size = url_ftell(pb) - start; 618 619 return ppi_size; 620} 621 622static void flush_packet(AVFormatContext *s) 623{ 624 ASFContext *asf = s->priv_data; 625 int packet_hdr_size, packet_filled_size; 626 627 assert(asf->packet_timestamp_end >= asf->packet_timestamp_start); 628 629 if (asf->is_streamed) { 630 put_chunk(s, 0x4424, s->packet_size, 0); 631 } 632 633 packet_hdr_size = put_payload_parsing_info( 634 s, 635 asf->packet_timestamp_start, 636 asf->packet_timestamp_end - asf->packet_timestamp_start, 637 asf->packet_nb_payloads, 638 asf->packet_size_left 639 ); 640 641 packet_filled_size = PACKET_SIZE - asf->packet_size_left; 642 assert(packet_hdr_size <= asf->packet_size_left); 643 memset(asf->packet_buf + packet_filled_size, 0, asf->packet_size_left); 644 645 put_buffer(s->pb, asf->packet_buf, s->packet_size - packet_hdr_size); 646 647 put_flush_packet(s->pb); 648 asf->nb_packets++; 649 asf->packet_nb_payloads = 0; 650 asf->packet_timestamp_start = -1; 651 asf->packet_timestamp_end = -1; 652 init_put_byte(&asf->pb, asf->packet_buf, s->packet_size, 1, 653 NULL, NULL, NULL, NULL); 654} 655 656static void put_payload_header( 657 AVFormatContext *s, 658 ASFStream *stream, 659 int presentation_time, 660 int m_obj_size, 661 int m_obj_offset, 662 int payload_len, 663 int flags 664 ) 665{ 666 ASFContext *asf = s->priv_data; 667 ByteIOContext *pb = &asf->pb; 668 int val; 669 670 val = stream->num; 671 if (flags & AV_PKT_FLAG_KEY) 672 val |= ASF_PL_FLAG_KEY_FRAME; 673 put_byte(pb, val); 674 675 put_byte(pb, stream->seq); //Media object number 676 put_le32(pb, m_obj_offset); //Offset Into Media Object 677 678 // Replicated Data shall be at least 8 bytes long. 679 // The first 4 bytes of data shall contain the 680 // Size of the Media Object that the payload belongs to. 681 // The next 4 bytes of data shall contain the 682 // Presentation Time for the media object that the payload belongs to. 683 put_byte(pb, ASF_PAYLOAD_REPLICATED_DATA_LENGTH); 684 685 put_le32(pb, m_obj_size); //Replicated Data - Media Object Size 686 put_le32(pb, presentation_time);//Replicated Data - Presentation Time 687 688 if (asf->multi_payloads_present){ 689 put_le16(pb, payload_len); //payload length 690 } 691} 692 693static void put_frame( 694 AVFormatContext *s, 695 ASFStream *stream, 696 AVStream *avst, 697 int timestamp, 698 const uint8_t *buf, 699 int m_obj_size, 700 int flags 701 ) 702{ 703 ASFContext *asf = s->priv_data; 704 int m_obj_offset, payload_len, frag_len1; 705 706 m_obj_offset = 0; 707 while (m_obj_offset < m_obj_size) { 708 payload_len = m_obj_size - m_obj_offset; 709 if (asf->packet_timestamp_start == -1) { 710 asf->multi_payloads_present = (payload_len < MULTI_PAYLOAD_CONSTANT); 711 712 asf->packet_size_left = PACKET_SIZE; 713 if (asf->multi_payloads_present){ 714 frag_len1 = MULTI_PAYLOAD_CONSTANT - 1; 715 } 716 else { 717 frag_len1 = SINGLE_PAYLOAD_DATA_LENGTH; 718 } 719 asf->packet_timestamp_start = timestamp; 720 } 721 else { 722 // multi payloads 723 frag_len1 = asf->packet_size_left - PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS - PACKET_HEADER_MIN_SIZE - 1; 724 725 if(frag_len1 < payload_len && avst->codec->codec_type == AVMEDIA_TYPE_AUDIO){ 726 flush_packet(s); 727 continue; 728 } 729 } 730 if (frag_len1 > 0) { 731 if (payload_len > frag_len1) 732 payload_len = frag_len1; 733 else if (payload_len == (frag_len1 - 1)) 734 payload_len = frag_len1 - 2; //additional byte need to put padding length 735 736 put_payload_header(s, stream, timestamp+PREROLL_TIME, m_obj_size, m_obj_offset, payload_len, flags); 737 put_buffer(&asf->pb, buf, payload_len); 738 739 if (asf->multi_payloads_present) 740 asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS); 741 else 742 asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD); 743 asf->packet_timestamp_end = timestamp; 744 745 asf->packet_nb_payloads++; 746 } else { 747 payload_len = 0; 748 } 749 m_obj_offset += payload_len; 750 buf += payload_len; 751 752 if (!asf->multi_payloads_present) 753 flush_packet(s); 754 else if (asf->packet_size_left <= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS + PACKET_HEADER_MIN_SIZE + 1)) 755 flush_packet(s); 756 } 757 stream->seq++; 758} 759 760static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) 761{ 762 ASFContext *asf = s->priv_data; 763 ASFStream *stream; 764 int64_t duration; 765 AVCodecContext *codec; 766 int64_t packet_st,pts; 767 int start_sec,i; 768 int flags= pkt->flags; 769 770 codec = s->streams[pkt->stream_index]->codec; 771 stream = &asf->streams[pkt->stream_index]; 772 773 if(codec->codec_type == AVMEDIA_TYPE_AUDIO) 774 flags &= ~AV_PKT_FLAG_KEY; 775 776 pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts; 777 assert(pts != AV_NOPTS_VALUE); 778 duration = pts * 10000; 779 asf->duration= FFMAX(asf->duration, duration + pkt->duration * 10000); 780 781 packet_st = asf->nb_packets; 782 put_frame(s, stream, s->streams[pkt->stream_index], pkt->dts, pkt->data, pkt->size, flags); 783 784 /* check index */ 785 if ((!asf->is_streamed) && (flags & AV_PKT_FLAG_KEY)) { 786 start_sec = (int)(duration / INT64_C(10000000)); 787 if (start_sec != (int)(asf->last_indexed_pts / INT64_C(10000000))) { 788 for(i=asf->nb_index_count;i<start_sec;i++) { 789 if (i>=asf->nb_index_memory_alloc) { 790 asf->nb_index_memory_alloc += ASF_INDEX_BLOCK; 791 asf->index_ptr = (ASFIndex*)av_realloc( asf->index_ptr, sizeof(ASFIndex) * asf->nb_index_memory_alloc ); 792 } 793 // store 794 asf->index_ptr[i].packet_number = (uint32_t)packet_st; 795 asf->index_ptr[i].packet_count = (uint16_t)(asf->nb_packets-packet_st); 796 asf->maximum_packet = FFMAX(asf->maximum_packet, (uint16_t)(asf->nb_packets-packet_st)); 797 } 798 asf->nb_index_count = start_sec; 799 asf->last_indexed_pts = duration; 800 } 801 } 802 return 0; 803} 804 805// 806static int asf_write_index(AVFormatContext *s, ASFIndex *index, uint16_t max, uint32_t count) 807{ 808 ByteIOContext *pb = s->pb; 809 int i; 810 811 put_guid(pb, &ff_asf_simple_index_header); 812 put_le64(pb, 24 + 16 + 8 + 4 + 4 + (4 + 2)*count); 813 put_guid(pb, &ff_asf_my_guid); 814 put_le64(pb, ASF_INDEXED_INTERVAL); 815 put_le32(pb, max); 816 put_le32(pb, count); 817 for(i=0; i<count; i++) { 818 put_le32(pb, index[i].packet_number); 819 put_le16(pb, index[i].packet_count); 820 } 821 822 return 0; 823} 824 825static int asf_write_trailer(AVFormatContext *s) 826{ 827 ASFContext *asf = s->priv_data; 828 int64_t file_size,data_size; 829 830 /* flush the current packet */ 831 if (asf->pb.buf_ptr > asf->pb.buffer) 832 flush_packet(s); 833 834 /* write index */ 835 data_size = url_ftell(s->pb); 836 if ((!asf->is_streamed) && (asf->nb_index_count != 0)) { 837 asf_write_index(s, asf->index_ptr, asf->maximum_packet, asf->nb_index_count); 838 } 839 put_flush_packet(s->pb); 840 841 if (asf->is_streamed || url_is_streamed(s->pb)) { 842 put_chunk(s, 0x4524, 0, 0); /* end of stream */ 843 } else { 844 /* rewrite an updated header */ 845 file_size = url_ftell(s->pb); 846 url_fseek(s->pb, 0, SEEK_SET); 847 asf_write_header1(s, file_size, data_size - asf->data_offset); 848 } 849 850 put_flush_packet(s->pb); 851 av_free(asf->index_ptr); 852 return 0; 853} 854 855#if CONFIG_ASF_MUXER 856AVOutputFormat asf_muxer = { 857 "asf", 858 NULL_IF_CONFIG_SMALL("ASF format"), 859 "video/x-ms-asf", 860 "asf,wmv,wma", 861 sizeof(ASFContext), 862#if CONFIG_LIBMP3LAME 863 CODEC_ID_MP3, 864#else 865 CODEC_ID_MP2, 866#endif 867 CODEC_ID_MSMPEG4V3, 868 asf_write_header, 869 asf_write_packet, 870 asf_write_trailer, 871 .flags = AVFMT_GLOBALHEADER, 872 .codec_tag= (const AVCodecTag* const []){codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0}, 873 .metadata_conv = ff_asf_metadata_conv, 874}; 875#endif 876 877#if CONFIG_ASF_STREAM_MUXER 878AVOutputFormat asf_stream_muxer = { 879 "asf_stream", 880 NULL_IF_CONFIG_SMALL("ASF format"), 881 "video/x-ms-asf", 882 "asf,wmv,wma", 883 sizeof(ASFContext), 884#if CONFIG_LIBMP3LAME 885 CODEC_ID_MP3, 886#else 887 CODEC_ID_MP2, 888#endif 889 CODEC_ID_MSMPEG4V3, 890 asf_write_stream_header, 891 asf_write_packet, 892 asf_write_trailer, 893 .flags = AVFMT_GLOBALHEADER, 894 .codec_tag= (const AVCodecTag* const []){codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0}, 895 .metadata_conv = ff_asf_metadata_conv, 896}; 897#endif //CONFIG_ASF_STREAM_MUXER 898