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 GUID *g) 201{ 202 assert(sizeof(*g) == 16); 203 put_buffer(s, *g, sizeof(*g)); 204} 205 206static void put_str16_nolen(ByteIOContext *s, const char *tag); 207static void put_str16(ByteIOContext *s, const char *tag) 208{ 209 put_le16(s,strlen(tag) + 1); 210 put_str16_nolen(s, tag); 211} 212 213static void put_str16_nolen(ByteIOContext *s, const char *tag) 214{ 215 int c; 216 217 do{ 218 c = (uint8_t)*tag++; 219 put_le16(s, c); 220 }while(c); 221} 222 223static int64_t put_header(ByteIOContext *pb, const GUID *g) 224{ 225 int64_t pos; 226 227 pos = url_ftell(pb); 228 put_guid(pb, g); 229 put_le64(pb, 24); 230 return pos; 231} 232 233/* update header size */ 234static void end_header(ByteIOContext *pb, int64_t pos) 235{ 236 int64_t pos1; 237 238 pos1 = url_ftell(pb); 239 url_fseek(pb, pos + 16, SEEK_SET); 240 put_le64(pb, pos1 - pos); 241 url_fseek(pb, pos1, SEEK_SET); 242} 243 244/* write an asf chunk (only used in streaming case) */ 245static void put_chunk(AVFormatContext *s, int type, int payload_length, int flags) 246{ 247 ASFContext *asf = s->priv_data; 248 ByteIOContext *pb = s->pb; 249 int length; 250 251 length = payload_length + 8; 252 put_le16(pb, type); 253 put_le16(pb, length); //size 254 put_le32(pb, asf->seqno);//sequence number 255 put_le16(pb, flags); /* unknown bytes */ 256 put_le16(pb, length); //size_confirm 257 asf->seqno++; 258} 259 260/* convert from unix to windows time */ 261static int64_t unix_to_file_time(int ti) 262{ 263 int64_t t; 264 265 t = ti * INT64_C(10000000); 266 t += INT64_C(116444736000000000); 267 return t; 268} 269 270/* write the header (used two times if non streamed) */ 271static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data_chunk_size) 272{ 273 ASFContext *asf = s->priv_data; 274 ByteIOContext *pb = s->pb; 275 AVMetadataTag *title, *author, *copyright, *comment; 276 int header_size, n, extra_size, extra_size2, wav_extra_size, file_time; 277 int has_title; 278 int metadata_count; 279 AVCodecContext *enc; 280 int64_t header_offset, cur_pos, hpos; 281 int bit_rate; 282 int64_t duration; 283 284 title = av_metadata_get(s->metadata, "title" , NULL, 0); 285 author = av_metadata_get(s->metadata, "author" , NULL, 0); 286 copyright = av_metadata_get(s->metadata, "copyright", NULL, 0); 287 comment = av_metadata_get(s->metadata, "comment" , NULL, 0); 288 289 duration = asf->duration + PREROLL_TIME * 10000; 290 has_title = title || author || copyright || comment; 291 metadata_count = s->metadata ? s->metadata->count : 0; 292 293 bit_rate = 0; 294 for(n=0;n<s->nb_streams;n++) { 295 enc = s->streams[n]->codec; 296 297 av_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */ 298 299 bit_rate += enc->bit_rate; 300 } 301 302 if (asf->is_streamed) { 303 put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */ 304 } 305 306 put_guid(pb, &ff_asf_header); 307 put_le64(pb, -1); /* header length, will be patched after */ 308 put_le32(pb, 3 + has_title + !!metadata_count + s->nb_streams); /* number of chunks in header */ 309 put_byte(pb, 1); /* ??? */ 310 put_byte(pb, 2); /* ??? */ 311 312 /* file header */ 313 header_offset = url_ftell(pb); 314 hpos = put_header(pb, &ff_asf_file_header); 315 put_guid(pb, &ff_asf_my_guid); 316 put_le64(pb, file_size); 317 file_time = 0; 318 put_le64(pb, unix_to_file_time(file_time)); 319 put_le64(pb, asf->nb_packets); /* number of packets */ 320 put_le64(pb, duration); /* end time stamp (in 100ns units) */ 321 put_le64(pb, asf->duration); /* duration (in 100ns units) */ 322 put_le64(pb, PREROLL_TIME); /* start time stamp */ 323 put_le32(pb, (asf->is_streamed || url_is_streamed(pb)) ? 3 : 2); /* ??? */ 324 put_le32(pb, s->packet_size); /* packet size */ 325 put_le32(pb, s->packet_size); /* packet size */ 326 put_le32(pb, bit_rate); /* Nominal data rate in bps */ 327 end_header(pb, hpos); 328 329 /* unknown headers */ 330 hpos = put_header(pb, &ff_asf_head1_guid); 331 put_guid(pb, &ff_asf_head2_guid); 332 put_le32(pb, 6); 333 put_le16(pb, 0); 334 end_header(pb, hpos); 335 336 /* title and other infos */ 337 if (has_title) { 338 hpos = put_header(pb, &ff_asf_comment_header); 339 put_le16(pb, title ? 2 * (strlen(title->value ) + 1) : 0); 340 put_le16(pb, author ? 2 * (strlen(author->value ) + 1) : 0); 341 put_le16(pb, copyright ? 2 * (strlen(copyright->value) + 1) : 0); 342 put_le16(pb, comment ? 2 * (strlen(comment->value ) + 1) : 0); 343 put_le16(pb, 0); 344 if (title ) put_str16_nolen(pb, title->value ); 345 if (author ) put_str16_nolen(pb, author->value ); 346 if (copyright) put_str16_nolen(pb, copyright->value); 347 if (comment ) put_str16_nolen(pb, comment->value ); 348 end_header(pb, hpos); 349 } 350 if (metadata_count) { 351 AVMetadataTag *tag = NULL; 352 hpos = put_header(pb, &ff_asf_extended_content_header); 353 put_le16(pb, metadata_count); 354 while ((tag = av_metadata_get(s->metadata, "", tag, AV_METADATA_IGNORE_SUFFIX))) { 355 put_le16(pb, 2*(strlen(tag->key) + 3) + 1); 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); 361 put_le16(pb, 2*strlen(tag->value) + 1); 362 put_str16_nolen(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 CODEC_TYPE_AUDIO: 379 wav_extra_size = 0; 380 extra_size = 18 + wav_extra_size; 381 extra_size2 = 8; 382 break; 383 default: 384 case CODEC_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 == CODEC_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 == CODEC_TYPE_AUDIO) { 407 /* WAVEFORMATEX header */ 408 int wavsize = 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 put_bmp_header(pb, enc, 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 453 enc = s->streams[n]->codec; 454 p = avcodec_find_encoder(enc->codec_id); 455 456 if(enc->codec_type == CODEC_TYPE_AUDIO) 457 put_le16(pb, 2); 458 else if(enc->codec_type == CODEC_TYPE_VIDEO) 459 put_le16(pb, 1); 460 else 461 put_le16(pb, -1); 462 463 if(enc->codec_id == CODEC_ID_WMAV2) 464 put_str16(pb, "Windows Media Audio V8"); 465 else 466 put_str16(pb, p ? p->name : enc->codec_name); 467 put_le16(pb, 0); /* no parameters */ 468 469 470 /* id */ 471 if (enc->codec_type == CODEC_TYPE_AUDIO) { 472 put_le16(pb, 2); 473 put_le16(pb, enc->codec_tag); 474 } else { 475 put_le16(pb, 4); 476 put_le32(pb, enc->codec_tag); 477 } 478 if(!enc->codec_tag) 479 return -1; 480 } 481 end_header(pb, hpos); 482 483 /* patch the header size fields */ 484 485 cur_pos = url_ftell(pb); 486 header_size = cur_pos - header_offset; 487 if (asf->is_streamed) { 488 header_size += 8 + 30 + 50; 489 490 url_fseek(pb, header_offset - 10 - 30, SEEK_SET); 491 put_le16(pb, header_size); 492 url_fseek(pb, header_offset - 2 - 30, SEEK_SET); 493 put_le16(pb, header_size); 494 495 header_size -= 8 + 30 + 50; 496 } 497 header_size += 24 + 6; 498 url_fseek(pb, header_offset - 14, SEEK_SET); 499 put_le64(pb, header_size); 500 url_fseek(pb, cur_pos, SEEK_SET); 501 502 /* movie chunk, followed by packets of packet_size */ 503 asf->data_offset = cur_pos; 504 put_guid(pb, &ff_asf_data_header); 505 put_le64(pb, data_chunk_size); 506 put_guid(pb, &ff_asf_my_guid); 507 put_le64(pb, asf->nb_packets); /* nb packets */ 508 put_byte(pb, 1); /* ??? */ 509 put_byte(pb, 1); /* ??? */ 510 return 0; 511} 512 513static int asf_write_header(AVFormatContext *s) 514{ 515 ASFContext *asf = s->priv_data; 516 517 s->packet_size = PACKET_SIZE; 518 asf->nb_packets = 0; 519 520 asf->last_indexed_pts = 0; 521 asf->index_ptr = av_malloc( sizeof(ASFIndex) * ASF_INDEX_BLOCK ); 522 asf->nb_index_memory_alloc = ASF_INDEX_BLOCK; 523 asf->nb_index_count = 0; 524 asf->maximum_packet = 0; 525 526 /* the data-chunk-size has to be 50, which is data_size - asf->data_offset 527 * at the moment this function is done. It is needed to use asf as 528 * streamable format. */ 529 if (asf_write_header1(s, 0, 50) < 0) { 530 //av_free(asf); 531 return -1; 532 } 533 534 put_flush_packet(s->pb); 535 536 asf->packet_nb_payloads = 0; 537 asf->packet_timestamp_start = -1; 538 asf->packet_timestamp_end = -1; 539 init_put_byte(&asf->pb, asf->packet_buf, s->packet_size, 1, 540 NULL, NULL, NULL, NULL); 541 542 return 0; 543} 544 545static int asf_write_stream_header(AVFormatContext *s) 546{ 547 ASFContext *asf = s->priv_data; 548 549 asf->is_streamed = 1; 550 551 return asf_write_header(s); 552} 553 554static int put_payload_parsing_info( 555 AVFormatContext *s, 556 unsigned int sendtime, 557 unsigned int duration, 558 int nb_payloads, 559 int padsize 560 ) 561{ 562 ASFContext *asf = s->priv_data; 563 ByteIOContext *pb = s->pb; 564 int ppi_size, i; 565 int64_t start= url_ftell(pb); 566 567 int iLengthTypeFlags = ASF_PPI_LENGTH_TYPE_FLAGS; 568 569 padsize -= PACKET_HEADER_MIN_SIZE; 570 if(asf->multi_payloads_present) 571 padsize--; 572 assert(padsize>=0); 573 574 put_byte(pb, ASF_PACKET_ERROR_CORRECTION_FLAGS); 575 for (i = 0; i < ASF_PACKET_ERROR_CORRECTION_DATA_SIZE; i++){ 576 put_byte(pb, 0x0); 577 } 578 579 if (asf->multi_payloads_present) 580 iLengthTypeFlags |= ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT; 581 582 if (padsize > 0) { 583 if (padsize < 256) 584 iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE; 585 else 586 iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD; 587 } 588 put_byte(pb, iLengthTypeFlags); 589 590 put_byte(pb, ASF_PPI_PROPERTY_FLAGS); 591 592 if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD) 593 put_le16(pb, padsize - 2); 594 if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE) 595 put_byte(pb, padsize - 1); 596 597 put_le32(pb, sendtime); 598 put_le16(pb, duration); 599 if (asf->multi_payloads_present) 600 put_byte(pb, nb_payloads | ASF_PAYLOAD_FLAGS); 601 602 ppi_size = url_ftell(pb) - start; 603 604 return ppi_size; 605} 606 607static void flush_packet(AVFormatContext *s) 608{ 609 ASFContext *asf = s->priv_data; 610 int packet_hdr_size, packet_filled_size; 611 612 assert(asf->packet_timestamp_end >= asf->packet_timestamp_start); 613 614 if (asf->is_streamed) { 615 put_chunk(s, 0x4424, s->packet_size, 0); 616 } 617 618 packet_hdr_size = put_payload_parsing_info( 619 s, 620 asf->packet_timestamp_start, 621 asf->packet_timestamp_end - asf->packet_timestamp_start, 622 asf->packet_nb_payloads, 623 asf->packet_size_left 624 ); 625 626 packet_filled_size = PACKET_SIZE - asf->packet_size_left; 627 assert(packet_hdr_size <= asf->packet_size_left); 628 memset(asf->packet_buf + packet_filled_size, 0, asf->packet_size_left); 629 630 put_buffer(s->pb, asf->packet_buf, s->packet_size - packet_hdr_size); 631 632 put_flush_packet(s->pb); 633 asf->nb_packets++; 634 asf->packet_nb_payloads = 0; 635 asf->packet_timestamp_start = -1; 636 asf->packet_timestamp_end = -1; 637 init_put_byte(&asf->pb, asf->packet_buf, s->packet_size, 1, 638 NULL, NULL, NULL, NULL); 639} 640 641static void put_payload_header( 642 AVFormatContext *s, 643 ASFStream *stream, 644 int presentation_time, 645 int m_obj_size, 646 int m_obj_offset, 647 int payload_len, 648 int flags 649 ) 650{ 651 ASFContext *asf = s->priv_data; 652 ByteIOContext *pb = &asf->pb; 653 int val; 654 655 val = stream->num; 656 if (flags & PKT_FLAG_KEY) 657 val |= ASF_PL_FLAG_KEY_FRAME; 658 put_byte(pb, val); 659 660 put_byte(pb, stream->seq); //Media object number 661 put_le32(pb, m_obj_offset); //Offset Into Media Object 662 663 // Replicated Data shall be at least 8 bytes long. 664 // The first 4 bytes of data shall contain the 665 // Size of the Media Object that the payload belongs to. 666 // The next 4 bytes of data shall contain the 667 // Presentation Time for the media object that the payload belongs to. 668 put_byte(pb, ASF_PAYLOAD_REPLICATED_DATA_LENGTH); 669 670 put_le32(pb, m_obj_size); //Replicated Data - Media Object Size 671 put_le32(pb, presentation_time);//Replicated Data - Presentation Time 672 673 if (asf->multi_payloads_present){ 674 put_le16(pb, payload_len); //payload length 675 } 676} 677 678static void put_frame( 679 AVFormatContext *s, 680 ASFStream *stream, 681 AVStream *avst, 682 int timestamp, 683 const uint8_t *buf, 684 int m_obj_size, 685 int flags 686 ) 687{ 688 ASFContext *asf = s->priv_data; 689 int m_obj_offset, payload_len, frag_len1; 690 691 m_obj_offset = 0; 692 while (m_obj_offset < m_obj_size) { 693 payload_len = m_obj_size - m_obj_offset; 694 if (asf->packet_timestamp_start == -1) { 695 asf->multi_payloads_present = (payload_len < MULTI_PAYLOAD_CONSTANT); 696 697 asf->packet_size_left = PACKET_SIZE; 698 if (asf->multi_payloads_present){ 699 frag_len1 = MULTI_PAYLOAD_CONSTANT - 1; 700 } 701 else { 702 frag_len1 = SINGLE_PAYLOAD_DATA_LENGTH; 703 } 704 asf->packet_timestamp_start = timestamp; 705 } 706 else { 707 // multi payloads 708 frag_len1 = asf->packet_size_left - PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS - PACKET_HEADER_MIN_SIZE - 1; 709 710 if(frag_len1 < payload_len && avst->codec->codec_type == CODEC_TYPE_AUDIO){ 711 flush_packet(s); 712 continue; 713 } 714 } 715 if (frag_len1 > 0) { 716 if (payload_len > frag_len1) 717 payload_len = frag_len1; 718 else if (payload_len == (frag_len1 - 1)) 719 payload_len = frag_len1 - 2; //additional byte need to put padding length 720 721 put_payload_header(s, stream, timestamp+PREROLL_TIME, m_obj_size, m_obj_offset, payload_len, flags); 722 put_buffer(&asf->pb, buf, payload_len); 723 724 if (asf->multi_payloads_present) 725 asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS); 726 else 727 asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD); 728 asf->packet_timestamp_end = timestamp; 729 730 asf->packet_nb_payloads++; 731 } else { 732 payload_len = 0; 733 } 734 m_obj_offset += payload_len; 735 buf += payload_len; 736 737 if (!asf->multi_payloads_present) 738 flush_packet(s); 739 else if (asf->packet_size_left <= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS + PACKET_HEADER_MIN_SIZE + 1)) 740 flush_packet(s); 741 } 742 stream->seq++; 743} 744 745static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) 746{ 747 ASFContext *asf = s->priv_data; 748 ASFStream *stream; 749 int64_t duration; 750 AVCodecContext *codec; 751 int64_t packet_st,pts; 752 int start_sec,i; 753 int flags= pkt->flags; 754 755 codec = s->streams[pkt->stream_index]->codec; 756 stream = &asf->streams[pkt->stream_index]; 757 758 if(codec->codec_type == CODEC_TYPE_AUDIO) 759 flags &= ~PKT_FLAG_KEY; 760 761 pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts; 762 assert(pts != AV_NOPTS_VALUE); 763 duration = pts * 10000; 764 asf->duration= FFMAX(asf->duration, duration + pkt->duration * 10000); 765 766 packet_st = asf->nb_packets; 767 put_frame(s, stream, s->streams[pkt->stream_index], pkt->dts, pkt->data, pkt->size, flags); 768 769 /* check index */ 770 if ((!asf->is_streamed) && (flags & PKT_FLAG_KEY)) { 771 start_sec = (int)(duration / INT64_C(10000000)); 772 if (start_sec != (int)(asf->last_indexed_pts / INT64_C(10000000))) { 773 for(i=asf->nb_index_count;i<start_sec;i++) { 774 if (i>=asf->nb_index_memory_alloc) { 775 asf->nb_index_memory_alloc += ASF_INDEX_BLOCK; 776 asf->index_ptr = (ASFIndex*)av_realloc( asf->index_ptr, sizeof(ASFIndex) * asf->nb_index_memory_alloc ); 777 } 778 // store 779 asf->index_ptr[i].packet_number = (uint32_t)packet_st; 780 asf->index_ptr[i].packet_count = (uint16_t)(asf->nb_packets-packet_st); 781 asf->maximum_packet = FFMAX(asf->maximum_packet, (uint16_t)(asf->nb_packets-packet_st)); 782 } 783 asf->nb_index_count = start_sec; 784 asf->last_indexed_pts = duration; 785 } 786 } 787 return 0; 788} 789 790// 791static int asf_write_index(AVFormatContext *s, ASFIndex *index, uint16_t max, uint32_t count) 792{ 793 ByteIOContext *pb = s->pb; 794 int i; 795 796 put_guid(pb, &ff_asf_simple_index_header); 797 put_le64(pb, 24 + 16 + 8 + 4 + 4 + (4 + 2)*count); 798 put_guid(pb, &ff_asf_my_guid); 799 put_le64(pb, ASF_INDEXED_INTERVAL); 800 put_le32(pb, max); 801 put_le32(pb, count); 802 for(i=0; i<count; i++) { 803 put_le32(pb, index[i].packet_number); 804 put_le16(pb, index[i].packet_count); 805 } 806 807 return 0; 808} 809 810static int asf_write_trailer(AVFormatContext *s) 811{ 812 ASFContext *asf = s->priv_data; 813 int64_t file_size,data_size; 814 815 /* flush the current packet */ 816 if (asf->pb.buf_ptr > asf->pb.buffer) 817 flush_packet(s); 818 819 /* write index */ 820 data_size = url_ftell(s->pb); 821 if ((!asf->is_streamed) && (asf->nb_index_count != 0)) { 822 asf_write_index(s, asf->index_ptr, asf->maximum_packet, asf->nb_index_count); 823 } 824 put_flush_packet(s->pb); 825 826 if (asf->is_streamed || url_is_streamed(s->pb)) { 827 put_chunk(s, 0x4524, 0, 0); /* end of stream */ 828 } else { 829 /* rewrite an updated header */ 830 file_size = url_ftell(s->pb); 831 url_fseek(s->pb, 0, SEEK_SET); 832 asf_write_header1(s, file_size, data_size - asf->data_offset); 833 } 834 835 put_flush_packet(s->pb); 836 av_free(asf->index_ptr); 837 return 0; 838} 839 840#if CONFIG_ASF_MUXER 841AVOutputFormat asf_muxer = { 842 "asf", 843 NULL_IF_CONFIG_SMALL("ASF format"), 844 "video/x-ms-asf", 845 "asf,wmv,wma", 846 sizeof(ASFContext), 847#if CONFIG_LIBMP3LAME 848 CODEC_ID_MP3, 849#else 850 CODEC_ID_MP2, 851#endif 852 CODEC_ID_MSMPEG4V3, 853 asf_write_header, 854 asf_write_packet, 855 asf_write_trailer, 856 .flags = AVFMT_GLOBALHEADER, 857 .codec_tag= (const AVCodecTag* const []){codec_asf_bmp_tags, codec_bmp_tags, codec_wav_tags, 0}, 858 .metadata_conv = ff_asf_metadata_conv, 859}; 860#endif 861 862#if CONFIG_ASF_STREAM_MUXER 863AVOutputFormat asf_stream_muxer = { 864 "asf_stream", 865 NULL_IF_CONFIG_SMALL("ASF format"), 866 "video/x-ms-asf", 867 "asf,wmv,wma", 868 sizeof(ASFContext), 869#if CONFIG_LIBMP3LAME 870 CODEC_ID_MP3, 871#else 872 CODEC_ID_MP2, 873#endif 874 CODEC_ID_MSMPEG4V3, 875 asf_write_stream_header, 876 asf_write_packet, 877 asf_write_trailer, 878 .flags = AVFMT_GLOBALHEADER, 879 .codec_tag= (const AVCodecTag* const []){codec_asf_bmp_tags, codec_bmp_tags, codec_wav_tags, 0}, 880 .metadata_conv = ff_asf_metadata_conv, 881}; 882#endif //CONFIG_ASF_STREAM_MUXER 883