00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "avformat.h"
00022 #include "riff.h"
00023 #include "asf.h"
00024
00025 #undef NDEBUG
00026 #include <assert.h>
00027
00028
00029 #define ASF_INDEXED_INTERVAL 10000000
00030 #define ASF_INDEX_BLOCK 600
00031
00032 #define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2
00033 #define ASF_PACKET_ERROR_CORRECTION_FLAGS (\
00034 ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT | \
00035 ASF_PACKET_ERROR_CORRECTION_DATA_SIZE\
00036 )
00037
00038 #if (ASF_PACKET_ERROR_CORRECTION_FLAGS != 0)
00039 # define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 1
00040 #else
00041 # define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 0
00042 #endif
00043
00044 #define ASF_PPI_PROPERTY_FLAGS (\
00045 ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE | \
00046 ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD | \
00047 ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE | \
00048 ASF_PL_FLAG_STREAM_NUMBER_LENGTH_FIELD_IS_BYTE \
00049 )
00050
00051 #define ASF_PPI_LENGTH_TYPE_FLAGS 0
00052
00053 #define ASF_PAYLOAD_FLAGS ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD
00054
00055 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
00056 # define ASF_PPI_SEQUENCE_FIELD_SIZE 1
00057 #endif
00058 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
00059 # define ASF_PPI_SEQUENCE_FIELD_SIZE 2
00060 #endif
00061 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
00062 # define ASF_PPI_SEQUENCE_FIELD_SIZE 4
00063 #endif
00064 #ifndef ASF_PPI_SEQUENCE_FIELD_SIZE
00065 # define ASF_PPI_SEQUENCE_FIELD_SIZE 0
00066 #endif
00067
00068
00069 #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
00070 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 1
00071 #endif
00072 #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
00073 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 2
00074 #endif
00075 #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
00076 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 4
00077 #endif
00078 #ifndef ASF_PPI_PACKET_LENGTH_FIELD_SIZE
00079 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 0
00080 #endif
00081
00082 #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
00083 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 1
00084 #endif
00085 #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
00086 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 2
00087 #endif
00088 #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
00089 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 4
00090 #endif
00091 #ifndef ASF_PPI_PADDING_LENGTH_FIELD_SIZE
00092 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 0
00093 #endif
00094
00095 #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
00096 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 1
00097 #endif
00098 #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
00099 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 2
00100 #endif
00101 #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
00102 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 4
00103 #endif
00104 #ifndef ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE
00105 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 0
00106 #endif
00107
00108 #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))
00109 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 1
00110 #endif
00111 #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))
00112 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 2
00113 #endif
00114 #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))
00115 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 4
00116 #endif
00117 #ifndef ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE
00118 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 0
00119 #endif
00120
00121 #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
00122 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 1
00123 #endif
00124 #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
00125 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 2
00126 #endif
00127 #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
00128 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 4
00129 #endif
00130 #ifndef ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE
00131 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 0
00132 #endif
00133
00134 #if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_BYTE == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
00135 # define ASF_PAYLOAD_LENGTH_FIELD_SIZE 1
00136 #endif
00137 #if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
00138 # define ASF_PAYLOAD_LENGTH_FIELD_SIZE 2
00139 #endif
00140 #ifndef ASF_PAYLOAD_LENGTH_FIELD_SIZE
00141 # define ASF_PAYLOAD_LENGTH_FIELD_SIZE 0
00142 #endif
00143
00144 #define PACKET_HEADER_MIN_SIZE (\
00145 ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE + \
00146 ASF_PACKET_ERROR_CORRECTION_DATA_SIZE + \
00147 1 + \
00148 1 + \
00149 ASF_PPI_PACKET_LENGTH_FIELD_SIZE + \
00150 ASF_PPI_SEQUENCE_FIELD_SIZE + \
00151 ASF_PPI_PADDING_LENGTH_FIELD_SIZE + \
00152 4 + \
00153 2 \
00154 )
00155
00156
00157
00158 #define ASF_PAYLOAD_REPLICATED_DATA_LENGTH 0x08
00159
00160 #define PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD (\
00161 1 + \
00162 ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \
00163 ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \
00164 ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \
00165 ASF_PAYLOAD_REPLICATED_DATA_LENGTH \
00166 )
00167
00168 #define PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS (\
00169 1 + \
00170 ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \
00171 ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \
00172 ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \
00173 ASF_PAYLOAD_REPLICATED_DATA_LENGTH + \
00174 ASF_PAYLOAD_LENGTH_FIELD_SIZE \
00175 )
00176
00177 #define SINGLE_PAYLOAD_DATA_LENGTH (\
00178 PACKET_SIZE - \
00179 PACKET_HEADER_MIN_SIZE - \
00180 PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD \
00181 )
00182
00183 #define MULTI_PAYLOAD_CONSTANT (\
00184 PACKET_SIZE - \
00185 PACKET_HEADER_MIN_SIZE - \
00186 1 - \
00187 2*PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS \
00188 )
00189
00190 static const AVCodecTag codec_asf_bmp_tags[] = {
00191 { CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') },
00192 { CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') },
00193 { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') },
00194 { CODEC_ID_NONE, 0 },
00195 };
00196
00197 #define PREROLL_TIME 3100
00198
00199 static void put_guid(ByteIOContext *s, const GUID *g)
00200 {
00201 assert(sizeof(*g) == 16);
00202 put_buffer(s, *g, sizeof(*g));
00203 }
00204
00205 static void put_str16_nolen(ByteIOContext *s, const char *tag);
00206 static void put_str16(ByteIOContext *s, const char *tag)
00207 {
00208 put_le16(s,strlen(tag) + 1);
00209 put_str16_nolen(s, tag);
00210 }
00211
00212 static void put_str16_nolen(ByteIOContext *s, const char *tag)
00213 {
00214 int c;
00215
00216 do{
00217 c = (uint8_t)*tag++;
00218 put_le16(s, c);
00219 }while(c);
00220 }
00221
00222 static int64_t put_header(ByteIOContext *pb, const GUID *g)
00223 {
00224 int64_t pos;
00225
00226 pos = url_ftell(pb);
00227 put_guid(pb, g);
00228 put_le64(pb, 24);
00229 return pos;
00230 }
00231
00232
00233 static void end_header(ByteIOContext *pb, int64_t pos)
00234 {
00235 int64_t pos1;
00236
00237 pos1 = url_ftell(pb);
00238 url_fseek(pb, pos + 16, SEEK_SET);
00239 put_le64(pb, pos1 - pos);
00240 url_fseek(pb, pos1, SEEK_SET);
00241 }
00242
00243
00244 static void put_chunk(AVFormatContext *s, int type, int payload_length, int flags)
00245 {
00246 ASFContext *asf = s->priv_data;
00247 ByteIOContext *pb = s->pb;
00248 int length;
00249
00250 length = payload_length + 8;
00251 put_le16(pb, type);
00252 put_le16(pb, length);
00253 put_le32(pb, asf->seqno);
00254 put_le16(pb, flags);
00255 put_le16(pb, length);
00256 asf->seqno++;
00257 }
00258
00259
00260 static int64_t unix_to_file_time(int ti)
00261 {
00262 int64_t t;
00263
00264 t = ti * INT64_C(10000000);
00265 t += INT64_C(116444736000000000);
00266 return t;
00267 }
00268
00269
00270 static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data_chunk_size)
00271 {
00272 ASFContext *asf = s->priv_data;
00273 ByteIOContext *pb = s->pb;
00274 int header_size, n, extra_size, extra_size2, wav_extra_size, file_time;
00275 int has_title;
00276 AVCodecContext *enc;
00277 int64_t header_offset, cur_pos, hpos;
00278 int bit_rate;
00279 int64_t duration;
00280
00281 duration = asf->duration + PREROLL_TIME * 10000;
00282 has_title = (s->title[0] || s->author[0] || s->copyright[0] || s->comment[0]);
00283
00284 bit_rate = 0;
00285 for(n=0;n<s->nb_streams;n++) {
00286 enc = s->streams[n]->codec;
00287
00288 av_set_pts_info(s->streams[n], 32, 1, 1000);
00289
00290 bit_rate += enc->bit_rate;
00291 }
00292
00293 if (asf->is_streamed) {
00294 put_chunk(s, 0x4824, 0, 0xc00);
00295 }
00296
00297 put_guid(pb, &asf_header);
00298 put_le64(pb, -1);
00299 put_le32(pb, 3 + has_title + s->nb_streams);
00300 put_byte(pb, 1);
00301 put_byte(pb, 2);
00302
00303
00304 header_offset = url_ftell(pb);
00305 hpos = put_header(pb, &file_header);
00306 put_guid(pb, &my_guid);
00307 put_le64(pb, file_size);
00308 file_time = 0;
00309 put_le64(pb, unix_to_file_time(file_time));
00310 put_le64(pb, asf->nb_packets);
00311 put_le64(pb, duration);
00312 put_le64(pb, asf->duration);
00313 put_le64(pb, PREROLL_TIME);
00314 put_le32(pb, (asf->is_streamed || url_is_streamed(pb)) ? 3 : 2);
00315 put_le32(pb, asf->packet_size);
00316 put_le32(pb, asf->packet_size);
00317 put_le32(pb, bit_rate);
00318 end_header(pb, hpos);
00319
00320
00321 hpos = put_header(pb, &head1_guid);
00322 put_guid(pb, &head2_guid);
00323 put_le32(pb, 6);
00324 put_le16(pb, 0);
00325 end_header(pb, hpos);
00326
00327
00328 if (has_title) {
00329 hpos = put_header(pb, &comment_header);
00330 if ( s->title[0] ) { put_le16(pb, 2 * (strlen(s->title ) + 1)); } else { put_le16(pb, 0); }
00331 if ( s->author[0] ) { put_le16(pb, 2 * (strlen(s->author ) + 1)); } else { put_le16(pb, 0); }
00332 if ( s->copyright[0] ) { put_le16(pb, 2 * (strlen(s->copyright) + 1)); } else { put_le16(pb, 0); }
00333 if ( s->comment[0] ) { put_le16(pb, 2 * (strlen(s->comment ) + 1)); } else { put_le16(pb, 0); }
00334 put_le16(pb, 0);
00335 if ( s->title[0] ) put_str16_nolen(pb, s->title);
00336 if ( s->author[0] ) put_str16_nolen(pb, s->author);
00337 if ( s->copyright[0] ) put_str16_nolen(pb, s->copyright);
00338 if ( s->comment[0] ) put_str16_nolen(pb, s->comment);
00339 end_header(pb, hpos);
00340 }
00341
00342
00343 for(n=0;n<s->nb_streams;n++) {
00344 int64_t es_pos;
00345
00346
00347 enc = s->streams[n]->codec;
00348 asf->streams[n].num = n + 1;
00349 asf->streams[n].seq = 0;
00350
00351
00352 switch(enc->codec_type) {
00353 case CODEC_TYPE_AUDIO:
00354 wav_extra_size = 0;
00355 extra_size = 18 + wav_extra_size;
00356 extra_size2 = 8;
00357 break;
00358 default:
00359 case CODEC_TYPE_VIDEO:
00360 wav_extra_size = enc->extradata_size;
00361 extra_size = 0x33 + wav_extra_size;
00362 extra_size2 = 0;
00363 break;
00364 }
00365
00366 hpos = put_header(pb, &stream_header);
00367 if (enc->codec_type == CODEC_TYPE_AUDIO) {
00368 put_guid(pb, &audio_stream);
00369 put_guid(pb, &audio_conceal_spread);
00370 } else {
00371 put_guid(pb, &video_stream);
00372 put_guid(pb, &video_conceal_none);
00373 }
00374 put_le64(pb, 0);
00375 es_pos = url_ftell(pb);
00376 put_le32(pb, extra_size);
00377 put_le32(pb, extra_size2);
00378 put_le16(pb, n + 1);
00379 put_le32(pb, 0);
00380
00381 if (enc->codec_type == CODEC_TYPE_AUDIO) {
00382
00383 int wavsize = put_wav_header(pb, enc);
00384 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)) {
00385 wavsize += 2;
00386 put_le16(pb, 0);
00387 }
00388
00389 if (wavsize < 0)
00390 return -1;
00391 if (wavsize != extra_size) {
00392 cur_pos = url_ftell(pb);
00393 url_fseek(pb, es_pos, SEEK_SET);
00394 put_le32(pb, wavsize);
00395 url_fseek(pb, cur_pos, SEEK_SET);
00396 }
00397
00398 put_byte(pb, 0x01);
00399 if(enc->codec_id == CODEC_ID_ADPCM_G726 || !enc->block_align){
00400 put_le16(pb, 0x0190);
00401 put_le16(pb, 0x0190);
00402 }else{
00403 put_le16(pb, enc->block_align);
00404 put_le16(pb, enc->block_align);
00405 }
00406 put_le16(pb, 0x01);
00407 put_byte(pb, 0x00);
00408 } else {
00409 put_le32(pb, enc->width);
00410 put_le32(pb, enc->height);
00411 put_byte(pb, 2);
00412 put_le16(pb, 40 + enc->extradata_size);
00413
00414
00415 put_bmp_header(pb, enc, codec_bmp_tags, 1);
00416 }
00417 end_header(pb, hpos);
00418 }
00419
00420
00421
00422 hpos = put_header(pb, &codec_comment_header);
00423 put_guid(pb, &codec_comment1_header);
00424 put_le32(pb, s->nb_streams);
00425 for(n=0;n<s->nb_streams;n++) {
00426 AVCodec *p;
00427
00428 enc = s->streams[n]->codec;
00429 p = avcodec_find_encoder(enc->codec_id);
00430
00431 if(enc->codec_type == CODEC_TYPE_AUDIO)
00432 put_le16(pb, 2);
00433 else if(enc->codec_type == CODEC_TYPE_VIDEO)
00434 put_le16(pb, 1);
00435 else
00436 put_le16(pb, -1);
00437
00438 if(enc->codec_id == CODEC_ID_WMAV2)
00439 put_str16(pb, "Windows Media Audio V8");
00440 else
00441 put_str16(pb, p ? p->name : enc->codec_name);
00442 put_le16(pb, 0);
00443
00444
00445
00446 if (enc->codec_type == CODEC_TYPE_AUDIO) {
00447 put_le16(pb, 2);
00448 put_le16(pb, enc->codec_tag);
00449 } else {
00450 put_le16(pb, 4);
00451 put_le32(pb, enc->codec_tag);
00452 }
00453 if(!enc->codec_tag)
00454 return -1;
00455 }
00456 end_header(pb, hpos);
00457
00458
00459
00460 cur_pos = url_ftell(pb);
00461 header_size = cur_pos - header_offset;
00462 if (asf->is_streamed) {
00463 header_size += 8 + 30 + 50;
00464
00465 url_fseek(pb, header_offset - 10 - 30, SEEK_SET);
00466 put_le16(pb, header_size);
00467 url_fseek(pb, header_offset - 2 - 30, SEEK_SET);
00468 put_le16(pb, header_size);
00469
00470 header_size -= 8 + 30 + 50;
00471 }
00472 header_size += 24 + 6;
00473 url_fseek(pb, header_offset - 14, SEEK_SET);
00474 put_le64(pb, header_size);
00475 url_fseek(pb, cur_pos, SEEK_SET);
00476
00477
00478 asf->data_offset = cur_pos;
00479 put_guid(pb, &data_header);
00480 put_le64(pb, data_chunk_size);
00481 put_guid(pb, &my_guid);
00482 put_le64(pb, asf->nb_packets);
00483 put_byte(pb, 1);
00484 put_byte(pb, 1);
00485 return 0;
00486 }
00487
00488 static int asf_write_header(AVFormatContext *s)
00489 {
00490 ASFContext *asf = s->priv_data;
00491
00492 asf->packet_size = PACKET_SIZE;
00493 asf->nb_packets = 0;
00494
00495 asf->last_indexed_pts = 0;
00496 asf->index_ptr = av_malloc( sizeof(ASFIndex) * ASF_INDEX_BLOCK );
00497 asf->nb_index_memory_alloc = ASF_INDEX_BLOCK;
00498 asf->nb_index_count = 0;
00499 asf->maximum_packet = 0;
00500
00501
00502
00503
00504 if (asf_write_header1(s, 0, 50) < 0) {
00505
00506 return -1;
00507 }
00508
00509 put_flush_packet(s->pb);
00510
00511 asf->packet_nb_payloads = 0;
00512 asf->packet_timestamp_start = -1;
00513 asf->packet_timestamp_end = -1;
00514 init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1,
00515 NULL, NULL, NULL, NULL);
00516
00517 return 0;
00518 }
00519
00520 static int asf_write_stream_header(AVFormatContext *s)
00521 {
00522 ASFContext *asf = s->priv_data;
00523
00524 asf->is_streamed = 1;
00525
00526 return asf_write_header(s);
00527 }
00528
00529 static int put_payload_parsing_info(
00530 AVFormatContext *s,
00531 unsigned int sendtime,
00532 unsigned int duration,
00533 int nb_payloads,
00534 int padsize
00535 )
00536 {
00537 ASFContext *asf = s->priv_data;
00538 ByteIOContext *pb = s->pb;
00539 int ppi_size, i;
00540 int64_t start= url_ftell(pb);
00541
00542 int iLengthTypeFlags = ASF_PPI_LENGTH_TYPE_FLAGS;
00543
00544 padsize -= PACKET_HEADER_MIN_SIZE;
00545 if(asf->multi_payloads_present)
00546 padsize--;
00547 assert(padsize>=0);
00548
00549 put_byte(pb, ASF_PACKET_ERROR_CORRECTION_FLAGS);
00550 for (i = 0; i < ASF_PACKET_ERROR_CORRECTION_DATA_SIZE; i++){
00551 put_byte(pb, 0x0);
00552 }
00553
00554 if (asf->multi_payloads_present)
00555 iLengthTypeFlags |= ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT;
00556
00557 if (padsize > 0) {
00558 if (padsize < 256)
00559 iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE;
00560 else
00561 iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD;
00562 }
00563 put_byte(pb, iLengthTypeFlags);
00564
00565 put_byte(pb, ASF_PPI_PROPERTY_FLAGS);
00566
00567 if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD)
00568 put_le16(pb, padsize - 2);
00569 if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE)
00570 put_byte(pb, padsize - 1);
00571
00572 put_le32(pb, sendtime);
00573 put_le16(pb, duration);
00574 if (asf->multi_payloads_present)
00575 put_byte(pb, nb_payloads | ASF_PAYLOAD_FLAGS);
00576
00577 ppi_size = url_ftell(pb) - start;
00578
00579 return ppi_size;
00580 }
00581
00582 static void flush_packet(AVFormatContext *s)
00583 {
00584 ASFContext *asf = s->priv_data;
00585 int packet_hdr_size, packet_filled_size;
00586
00587 assert(asf->packet_timestamp_end >= asf->packet_timestamp_start);
00588
00589 if (asf->is_streamed) {
00590 put_chunk(s, 0x4424, asf->packet_size, 0);
00591 }
00592
00593 packet_hdr_size = put_payload_parsing_info(
00594 s,
00595 asf->packet_timestamp_start,
00596 asf->packet_timestamp_end - asf->packet_timestamp_start,
00597 asf->packet_nb_payloads,
00598 asf->packet_size_left
00599 );
00600
00601 packet_filled_size = PACKET_SIZE - asf->packet_size_left;
00602 assert(packet_hdr_size <= asf->packet_size_left);
00603 memset(asf->packet_buf + packet_filled_size, 0, asf->packet_size_left);
00604
00605 put_buffer(s->pb, asf->packet_buf, asf->packet_size - packet_hdr_size);
00606
00607 put_flush_packet(s->pb);
00608 asf->nb_packets++;
00609 asf->packet_nb_payloads = 0;
00610 asf->packet_timestamp_start = -1;
00611 asf->packet_timestamp_end = -1;
00612 init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1,
00613 NULL, NULL, NULL, NULL);
00614 }
00615
00616 static void put_payload_header(
00617 AVFormatContext *s,
00618 ASFStream *stream,
00619 int presentation_time,
00620 int m_obj_size,
00621 int m_obj_offset,
00622 int payload_len,
00623 int flags
00624 )
00625 {
00626 ASFContext *asf = s->priv_data;
00627 ByteIOContext *pb = &asf->pb;
00628 int val;
00629
00630 val = stream->num;
00631 if (flags & PKT_FLAG_KEY)
00632 val |= ASF_PL_FLAG_KEY_FRAME;
00633 put_byte(pb, val);
00634
00635 put_byte(pb, stream->seq);
00636 put_le32(pb, m_obj_offset);
00637
00638
00639
00640
00641
00642
00643 put_byte(pb, ASF_PAYLOAD_REPLICATED_DATA_LENGTH);
00644
00645 put_le32(pb, m_obj_size);
00646 put_le32(pb, presentation_time);
00647
00648 if (asf->multi_payloads_present){
00649 put_le16(pb, payload_len);
00650 }
00651 }
00652
00653 static void put_frame(
00654 AVFormatContext *s,
00655 ASFStream *stream,
00656 AVStream *avst,
00657 int timestamp,
00658 const uint8_t *buf,
00659 int m_obj_size,
00660 int flags
00661 )
00662 {
00663 ASFContext *asf = s->priv_data;
00664 int m_obj_offset, payload_len, frag_len1;
00665
00666 m_obj_offset = 0;
00667 while (m_obj_offset < m_obj_size) {
00668 payload_len = m_obj_size - m_obj_offset;
00669 if (asf->packet_timestamp_start == -1) {
00670 asf->multi_payloads_present = (payload_len < MULTI_PAYLOAD_CONSTANT);
00671
00672 asf->packet_size_left = PACKET_SIZE;
00673 if (asf->multi_payloads_present){
00674 frag_len1 = MULTI_PAYLOAD_CONSTANT - 1;
00675 }
00676 else {
00677 frag_len1 = SINGLE_PAYLOAD_DATA_LENGTH;
00678 }
00679 asf->packet_timestamp_start = timestamp;
00680 }
00681 else {
00682
00683 frag_len1 = asf->packet_size_left - PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS - PACKET_HEADER_MIN_SIZE - 1;
00684
00685 if(frag_len1 < payload_len && avst->codec->codec_type == CODEC_TYPE_AUDIO){
00686 flush_packet(s);
00687 continue;
00688 }
00689 }
00690 if (frag_len1 > 0) {
00691 if (payload_len > frag_len1)
00692 payload_len = frag_len1;
00693 else if (payload_len == (frag_len1 - 1))
00694 payload_len = frag_len1 - 2;
00695
00696 put_payload_header(s, stream, timestamp+PREROLL_TIME, m_obj_size, m_obj_offset, payload_len, flags);
00697 put_buffer(&asf->pb, buf, payload_len);
00698
00699 if (asf->multi_payloads_present)
00700 asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS);
00701 else
00702 asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD);
00703 asf->packet_timestamp_end = timestamp;
00704
00705 asf->packet_nb_payloads++;
00706 } else {
00707 payload_len = 0;
00708 }
00709 m_obj_offset += payload_len;
00710 buf += payload_len;
00711
00712 if (!asf->multi_payloads_present)
00713 flush_packet(s);
00714 else if (asf->packet_size_left <= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS + PACKET_HEADER_MIN_SIZE + 1))
00715 flush_packet(s);
00716 }
00717 stream->seq++;
00718 }
00719
00720 static int asf_write_packet(AVFormatContext *s, AVPacket *pkt)
00721 {
00722 ASFContext *asf = s->priv_data;
00723 ASFStream *stream;
00724 int64_t duration;
00725 AVCodecContext *codec;
00726 int64_t packet_st,pts;
00727 int start_sec,i;
00728 int flags= pkt->flags;
00729
00730 codec = s->streams[pkt->stream_index]->codec;
00731 stream = &asf->streams[pkt->stream_index];
00732
00733 if(codec->codec_type == CODEC_TYPE_AUDIO)
00734 flags &= ~PKT_FLAG_KEY;
00735
00736
00737 pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts;
00738 assert(pts != AV_NOPTS_VALUE);
00739 duration = pts * 10000;
00740 asf->duration= FFMAX(asf->duration, duration);
00741
00742 packet_st = asf->nb_packets;
00743 put_frame(s, stream, s->streams[pkt->stream_index], pkt->dts, pkt->data, pkt->size, flags);
00744
00745
00746 if ((!asf->is_streamed) && (flags & PKT_FLAG_KEY)) {
00747 start_sec = (int)(duration / INT64_C(10000000));
00748 if (start_sec != (int)(asf->last_indexed_pts / INT64_C(10000000))) {
00749 for(i=asf->nb_index_count;i<start_sec;i++) {
00750 if (i>=asf->nb_index_memory_alloc) {
00751 asf->nb_index_memory_alloc += ASF_INDEX_BLOCK;
00752 asf->index_ptr = (ASFIndex*)av_realloc( asf->index_ptr, sizeof(ASFIndex) * asf->nb_index_memory_alloc );
00753 }
00754
00755 asf->index_ptr[i].packet_number = (uint32_t)packet_st;
00756 asf->index_ptr[i].packet_count = (uint16_t)(asf->nb_packets-packet_st);
00757 asf->maximum_packet = FFMAX(asf->maximum_packet, (uint16_t)(asf->nb_packets-packet_st));
00758 }
00759 asf->nb_index_count = start_sec;
00760 asf->last_indexed_pts = duration;
00761 }
00762 }
00763 return 0;
00764 }
00765
00766
00767 static int asf_write_index(AVFormatContext *s, ASFIndex *index, uint16_t max, uint32_t count)
00768 {
00769 ByteIOContext *pb = s->pb;
00770 int i;
00771
00772 put_guid(pb, &simple_index_header);
00773 put_le64(pb, 24 + 16 + 8 + 4 + 4 + (4 + 2)*count);
00774 put_guid(pb, &my_guid);
00775 put_le64(pb, ASF_INDEXED_INTERVAL);
00776 put_le32(pb, max);
00777 put_le32(pb, count);
00778 for(i=0; i<count; i++) {
00779 put_le32(pb, index[i].packet_number);
00780 put_le16(pb, index[i].packet_count);
00781 }
00782
00783 return 0;
00784 }
00785
00786 static int asf_write_trailer(AVFormatContext *s)
00787 {
00788 ASFContext *asf = s->priv_data;
00789 int64_t file_size,data_size;
00790
00791
00792 if (asf->pb.buf_ptr > asf->pb.buffer)
00793 flush_packet(s);
00794
00795
00796 data_size = url_ftell(s->pb);
00797 if ((!asf->is_streamed) && (asf->nb_index_count != 0)) {
00798 asf_write_index(s, asf->index_ptr, asf->maximum_packet, asf->nb_index_count);
00799 }
00800 put_flush_packet(s->pb);
00801
00802 if (asf->is_streamed || url_is_streamed(s->pb)) {
00803 put_chunk(s, 0x4524, 0, 0);
00804 } else {
00805
00806 file_size = url_ftell(s->pb);
00807 url_fseek(s->pb, 0, SEEK_SET);
00808 asf_write_header1(s, file_size, data_size - asf->data_offset);
00809 }
00810
00811 put_flush_packet(s->pb);
00812 av_free(asf->index_ptr);
00813 return 0;
00814 }
00815
00816 #ifdef CONFIG_ASF_MUXER
00817 AVOutputFormat asf_muxer = {
00818 "asf",
00819 "asf format",
00820 "video/x-ms-asf",
00821 "asf,wmv,wma",
00822 sizeof(ASFContext),
00823 #ifdef CONFIG_LIBMP3LAME
00824 CODEC_ID_MP3,
00825 #else
00826 CODEC_ID_MP2,
00827 #endif
00828 CODEC_ID_MSMPEG4V3,
00829 asf_write_header,
00830 asf_write_packet,
00831 asf_write_trailer,
00832 .flags = AVFMT_GLOBALHEADER,
00833 .codec_tag= (const AVCodecTag*[]){codec_asf_bmp_tags, codec_bmp_tags, codec_wav_tags, 0},
00834 };
00835 #endif
00836
00837 #ifdef CONFIG_ASF_STREAM_MUXER
00838 AVOutputFormat asf_stream_muxer = {
00839 "asf_stream",
00840 "asf format",
00841 "video/x-ms-asf",
00842 "asf,wmv,wma",
00843 sizeof(ASFContext),
00844 #ifdef CONFIG_LIBMP3LAME
00845 CODEC_ID_MP3,
00846 #else
00847 CODEC_ID_MP2,
00848 #endif
00849 CODEC_ID_MSMPEG4V3,
00850 asf_write_stream_header,
00851 asf_write_packet,
00852 asf_write_trailer,
00853 .flags = AVFMT_GLOBALHEADER,
00854 .codec_tag= (const AVCodecTag*[]){codec_asf_bmp_tags, codec_bmp_tags, codec_wav_tags, 0},
00855 };
00856 #endif //CONFIG_ASF_STREAM_MUXER