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