asfenc: remove an unused variable
[libav.git] / libavformat / asfenc.c
CommitLineData
542993b0 1/*
f26be477 2 * ASF muxer
406792e7 3 * Copyright (c) 2000, 2001 Fabrice Bellard
542993b0 4 *
2912e87a 5 * This file is part of Libav.
b78e7197 6 *
2912e87a 7 * Libav is free software; you can redistribute it and/or
542993b0
KA
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
b78e7197 10 * version 2.1 of the License, or (at your option) any later version.
542993b0 11 *
2912e87a 12 * Libav is distributed in the hope that it will be useful,
542993b0
KA
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
2912e87a 18 * License along with Libav; if not, write to the Free Software
5509bffa 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
542993b0 20 */
48a4ffa7
DB
21
22#include "libavutil/dict.h"
bb461370 23#include "libavutil/mathematics.h"
542993b0 24#include "avformat.h"
48a4ffa7 25#include "avio_internal.h"
c3f9ebf7 26#include "internal.h"
9d9f4119 27#include "riff.h"
542993b0
KA
28#include "asf.h"
29
30#undef NDEBUG
31#include <assert.h>
32
982e53fe 33
bb270c08
DB
34#define ASF_INDEXED_INTERVAL 10000000
35#define ASF_INDEX_BLOCK 600
982e53fe 36
615b92fd 37#define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2
48a4ffa7
DB
38#define ASF_PACKET_ERROR_CORRECTION_FLAGS \
39 (ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT | \
40 ASF_PACKET_ERROR_CORRECTION_DATA_SIZE)
615b92fd
KA
41
42#if (ASF_PACKET_ERROR_CORRECTION_FLAGS != 0)
43# define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 1
44#else
45# define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 0
46#endif
47
48a4ffa7
DB
48#define ASF_PPI_PROPERTY_FLAGS \
49 (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE | \
50 ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD | \
51 ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE | \
52 ASF_PL_FLAG_STREAM_NUMBER_LENGTH_FIELD_IS_BYTE)
615b92fd
KA
53
54#define ASF_PPI_LENGTH_TYPE_FLAGS 0
55
56#define ASF_PAYLOAD_FLAGS ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD
57
58#if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
59# define ASF_PPI_SEQUENCE_FIELD_SIZE 1
60#endif
61#if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
62# define ASF_PPI_SEQUENCE_FIELD_SIZE 2
63#endif
64#if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
65# define ASF_PPI_SEQUENCE_FIELD_SIZE 4
66#endif
67#ifndef ASF_PPI_SEQUENCE_FIELD_SIZE
68# define ASF_PPI_SEQUENCE_FIELD_SIZE 0
69#endif
70
615b92fd
KA
71#if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
72# define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 1
73#endif
74#if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
75# define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 2
76#endif
77#if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
78# define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 4
79#endif
80#ifndef ASF_PPI_PACKET_LENGTH_FIELD_SIZE
81# define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 0
82#endif
83
84#if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
85# define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 1
86#endif
87#if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
88# define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 2
89#endif
90#if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
91# define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 4
92#endif
93#ifndef ASF_PPI_PADDING_LENGTH_FIELD_SIZE
94# define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 0
95#endif
96
97#if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
98# define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 1
99#endif
100#if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
101# define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 2
102#endif
103#if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
104# define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 4
105#endif
106#ifndef ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE
107# define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 0
108#endif
109
110#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))
111# define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 1
112#endif
113#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))
114# define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 2
115#endif
116#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))
117# define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 4
118#endif
119#ifndef ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE
120# define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 0
121#endif
122
123#if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
124# define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 1
125#endif
126#if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
127# define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 2
128#endif
129#if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
130# define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 4
131#endif
132#ifndef ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE
133# define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 0
134#endif
135
136#if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_BYTE == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
137# define ASF_PAYLOAD_LENGTH_FIELD_SIZE 1
138#endif
139#if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
140# define ASF_PAYLOAD_LENGTH_FIELD_SIZE 2
141#endif
142#ifndef ASF_PAYLOAD_LENGTH_FIELD_SIZE
143# define ASF_PAYLOAD_LENGTH_FIELD_SIZE 0
144#endif
145
48a4ffa7
DB
146#define PACKET_HEADER_MIN_SIZE \
147 (ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE + \
148 ASF_PACKET_ERROR_CORRECTION_DATA_SIZE + \
149 1 + /* Length Type Flags */ \
150 1 + /* Property Flags */ \
151 ASF_PPI_PACKET_LENGTH_FIELD_SIZE + \
152 ASF_PPI_SEQUENCE_FIELD_SIZE + \
153 ASF_PPI_PADDING_LENGTH_FIELD_SIZE + \
154 4 + /* Send Time Field */ \
155 2) /* Duration Field */
615b92fd
KA
156
157// Replicated Data shall be at least 8 bytes long.
158#define ASF_PAYLOAD_REPLICATED_DATA_LENGTH 0x08
159
48a4ffa7
DB
160#define PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD \
161 (1 + /* Stream Number */ \
162 ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \
163 ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \
164 ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \
165 ASF_PAYLOAD_REPLICATED_DATA_LENGTH)
166
167#define PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS \
168 (1 + /* Stream Number */ \
169 ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \
170 ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \
171 ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \
172 ASF_PAYLOAD_REPLICATED_DATA_LENGTH + \
173 ASF_PAYLOAD_LENGTH_FIELD_SIZE)
174
175#define SINGLE_PAYLOAD_DATA_LENGTH \
176 (PACKET_SIZE - \
177 PACKET_HEADER_MIN_SIZE - \
178 PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD)
179
180#define MULTI_PAYLOAD_CONSTANT \
181 (PACKET_SIZE - \
182 PACKET_HEADER_MIN_SIZE - \
183 1 - /* Payload Flags */ \
184 2 * PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS)
615b92fd 185
c53b5dda
VP
186#define DATA_HEADER_SIZE 50
187
b08569a2
AH
188typedef struct ASFStream {
189 int num;
190 unsigned char seq;
191 /* use for reading */
192 AVPacket pkt;
193 int frag_offset;
194 int timestamp;
b08569a2
AH
195
196 int ds_span; /* descrambling */
197 int ds_packet_size;
198 int ds_chunk_size;
199
200 int64_t packet_pos;
201
202 uint16_t stream_language_index;
203
204 int palette_changed;
205 uint32_t palette[256];
206} ASFStream;
207
daf8cf35 208typedef struct ASFContext {
4bc328a2
AK
209 uint32_t seqno;
210 int is_streamed;
211 ASFStream streams[128]; ///< it's max number and it's not that big
212 /* non streamed additonnal info */
213 uint64_t nb_packets; ///< how many packets are there in the file, invalid if broadcasting
ff3db937 214 uint64_t duration; ///< in ms
4bc328a2
AK
215 /* packet filling */
216 unsigned char multi_payloads_present;
217 int packet_size_left;
218 int packet_timestamp_start;
219 int packet_timestamp_end;
220 unsigned int packet_nb_payloads;
221 uint8_t packet_buf[PACKET_SIZE];
ae628ec1 222 AVIOContext pb;
4bc328a2
AK
223 /* only for reading */
224 uint64_t data_offset; ///< beginning of the first data packet
225
226 int64_t last_indexed_pts;
48a4ffa7 227 ASFIndex *index_ptr;
4bc328a2
AK
228 uint32_t nb_index_count;
229 uint32_t nb_index_memory_alloc;
230 uint16_t maximum_packet;
231} ASFContext;
232
7caf0cc6 233static const AVCodecTag codec_asf_bmp_tags[] = {
48a4ffa7
DB
234 { AV_CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') },
235 { AV_CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') },
36ef5369 236 { AV_CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') },
48a4ffa7 237 { AV_CODEC_ID_NONE, 0 },
7caf0cc6
MN
238};
239
3caa0d93 240#define PREROLL_TIME 3100
615b92fd 241
ae628ec1 242static void put_guid(AVIOContext *s, const ff_asf_guid *g)
542993b0 243{
24c14d6d 244 assert(sizeof(*g) == 16);
77eb5504 245 avio_write(s, *g, sizeof(*g));
542993b0
KA
246}
247
ae628ec1 248static void put_str16(AVIOContext *s, const char *tag)
cba2f6d5
AK
249{
250 int len;
251 uint8_t *pb;
ae628ec1 252 AVIOContext *dyn_buf;
b92c5452 253 if (avio_open_dyn_buf(&dyn_buf) < 0)
cba2f6d5
AK
254 return;
255
dccbd97d 256 avio_put_str16le(dyn_buf, tag);
6dc7d80d 257 len = avio_close_dyn_buf(dyn_buf, &pb);
77eb5504
AK
258 avio_wl16(s, len);
259 avio_write(s, pb, len);
cba2f6d5 260 av_freep(&pb);
542993b0
KA
261}
262
ae628ec1 263static int64_t put_header(AVIOContext *pb, const ff_asf_guid *g)
542993b0
KA
264{
265 int64_t pos;
266
a2704c97 267 pos = avio_tell(pb);
542993b0 268 put_guid(pb, g);
77eb5504 269 avio_wl64(pb, 24);
542993b0
KA
270 return pos;
271}
272
273/* update header size */
ae628ec1 274static void end_header(AVIOContext *pb, int64_t pos)
542993b0
KA
275{
276 int64_t pos1;
277
a2704c97 278 pos1 = avio_tell(pb);
6b4aa5da 279 avio_seek(pb, pos + 16, SEEK_SET);
77eb5504 280 avio_wl64(pb, pos1 - pos);
6b4aa5da 281 avio_seek(pb, pos1, SEEK_SET);
542993b0
KA
282}
283
284/* write an asf chunk (only used in streaming case) */
48a4ffa7
DB
285static void put_chunk(AVFormatContext *s, int type,
286 int payload_length, int flags)
542993b0
KA
287{
288 ASFContext *asf = s->priv_data;
ae628ec1 289 AVIOContext *pb = s->pb;
542993b0
KA
290 int length;
291
292 length = payload_length + 8;
77eb5504 293 avio_wl16(pb, type);
48a4ffa7
DB
294 avio_wl16(pb, length); // size
295 avio_wl32(pb, asf->seqno); // sequence number
296 avio_wl16(pb, flags); // unknown bytes
297 avio_wl16(pb, length); // size_confirm
542993b0
KA
298 asf->seqno++;
299}
300
301/* convert from unix to windows time */
302static int64_t unix_to_file_time(int ti)
303{
304 int64_t t;
305
48a4ffa7 306 t = ti * INT64_C(10000000);
8da9266c 307 t += INT64_C(116444736000000000);
542993b0
KA
308 return t;
309}
310
bb461370
VP
311static int32_t get_send_time(ASFContext *asf, int64_t pres_time, uint64_t *offset)
312{
313 int i;
314 int32_t send_time = 0;
315 *offset = asf->data_offset + DATA_HEADER_SIZE;
316 for (i = 0; i < asf->nb_index_count; i++) {
317 if (pres_time <= asf->index_ptr[i].send_time)
318 break;
319 send_time = asf->index_ptr[i].send_time;
320 *offset = asf->index_ptr[i].offset;
321 }
322
323 return send_time / 10000;
324}
325
326static int asf_write_markers(AVFormatContext *s)
327{
328 ASFContext *asf = s->priv_data;
329 AVIOContext *pb = s->pb;
330 int i;
331 AVRational scale = {1, 10000000};
332 int64_t hpos = put_header(pb, &ff_asf_marker_header);
333
334 put_guid(pb, &ff_asf_reserved_4); // ASF spec mandates this reserved value
335 avio_wl32(pb, s->nb_chapters); // markers count
336 avio_wl16(pb, 0); // ASF spec mandates 0 for this
337 avio_wl16(pb, 0); // name length 0, no name given
338
339 for (i = 0; i < s->nb_chapters; i++) {
340 AVChapter *c = s->chapters[i];
341 AVDictionaryEntry *t = av_dict_get(c->metadata, "title", NULL, 0);
342 int64_t pres_time = av_rescale_q(c->start, c->time_base, scale);
343 uint64_t offset;
344 int32_t send_time = get_send_time(asf, pres_time, &offset);
345 int len = 0;
346 uint8_t *buf;
347 AVIOContext *dyn_buf;
348 if (t) {
349 if (avio_open_dyn_buf(&dyn_buf) < 0)
350 return AVERROR(ENOMEM);
351 avio_put_str16le(dyn_buf, t->value);
352 len = avio_close_dyn_buf(dyn_buf, &buf);
353 }
354 avio_wl64(pb, offset); // offset of the packet with send_time
355 avio_wl64(pb, pres_time + PREROLL_TIME * 10000); // presentation time
356 avio_wl16(pb, 12 + len); // entry length
357 avio_wl32(pb, send_time); // send time
358 avio_wl32(pb, 0); // flags, should be 0
359 avio_wl32(pb, len / 2); // marker desc length in WCHARS!
360 if (t) {
361 avio_write(pb, buf, len); // marker desc
362 av_freep(&buf);
363 }
364 }
365 end_header(pb, hpos);
366 return 0;
367}
368
542993b0 369/* write the header (used two times if non streamed) */
48a4ffa7
DB
370static int asf_write_header1(AVFormatContext *s, int64_t file_size,
371 int64_t data_chunk_size)
542993b0
KA
372{
373 ASFContext *asf = s->priv_data;
ae628ec1 374 AVIOContext *pb = s->pb;
d2d67e42 375 AVDictionaryEntry *tags[5];
542993b0
KA
376 int header_size, n, extra_size, extra_size2, wav_extra_size, file_time;
377 int has_title;
488227c5 378 int metadata_count;
9200514a 379 AVCodecParameters *par;
542993b0
KA
380 int64_t header_offset, cur_pos, hpos;
381 int bit_rate;
ff3db937 382 uint64_t play_duration, send_duration;
542993b0 383
ad7768f4 384 ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL);
03700d39 385
48a4ffa7
DB
386 tags[0] = av_dict_get(s->metadata, "title", NULL, 0);
387 tags[1] = av_dict_get(s->metadata, "author", NULL, 0);
d2d67e42 388 tags[2] = av_dict_get(s->metadata, "copyright", NULL, 0);
48a4ffa7
DB
389 tags[3] = av_dict_get(s->metadata, "comment", NULL, 0);
390 tags[4] = av_dict_get(s->metadata, "rating", NULL, 0);
300f24f3 391
ff3db937
AK
392 if (asf->duration > UINT64_MAX / 10000 - PREROLL_TIME) {
393 av_log(s, AV_LOG_WARNING, "Duration %"PRIu64" too large\n", asf->duration);
394 if (s->error_recognition & AV_EF_EXPLODE)
395 return AVERROR(ERANGE);
396 send_duration = 0;
397 play_duration = 0;
398 } else {
399 send_duration = asf->duration * 10000;
400 play_duration = (asf->duration + PREROLL_TIME) * 10000;
401 }
402
48a4ffa7 403 has_title = tags[0] || tags[1] || tags[2] || tags[3] || tags[4];
987170cb 404 metadata_count = av_dict_count(s->metadata);
542993b0
KA
405
406 bit_rate = 0;
48a4ffa7 407 for (n = 0; n < s->nb_streams; n++) {
9200514a 408 par = s->streams[n]->codecpar;
542993b0 409
c3f9ebf7 410 avpriv_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */
9ee91c2f 411
9200514a 412 bit_rate += par->bit_rate;
542993b0
KA
413 }
414
415 if (asf->is_streamed) {
416 put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */
417 }
418
17af0525 419 put_guid(pb, &ff_asf_header);
77eb5504
AK
420 avio_wl64(pb, -1); /* header length, will be patched after */
421 avio_wl32(pb, 3 + has_title + !!metadata_count + s->nb_streams); /* number of chunks in header */
422 avio_w8(pb, 1); /* ??? */
423 avio_w8(pb, 2); /* ??? */
542993b0
KA
424
425 /* file header */
a2704c97 426 header_offset = avio_tell(pb);
48a4ffa7 427 hpos = put_header(pb, &ff_asf_file_header);
17af0525 428 put_guid(pb, &ff_asf_my_guid);
77eb5504 429 avio_wl64(pb, file_size);
542993b0 430 file_time = 0;
77eb5504
AK
431 avio_wl64(pb, unix_to_file_time(file_time));
432 avio_wl64(pb, asf->nb_packets); /* number of packets */
ff3db937
AK
433 avio_wl64(pb, play_duration); /* end time stamp (in 100ns units) */
434 avio_wl64(pb, send_duration); /* duration (in 100ns units) */
77eb5504 435 avio_wl64(pb, PREROLL_TIME); /* start time stamp */
48a4ffa7 436 avio_wl32(pb, (asf->is_streamed || !pb->seekable) ? 3 : 2); /* ??? */
77eb5504
AK
437 avio_wl32(pb, s->packet_size); /* packet size */
438 avio_wl32(pb, s->packet_size); /* packet size */
439 avio_wl32(pb, bit_rate); /* Nominal data rate in bps */
542993b0
KA
440 end_header(pb, hpos);
441
442 /* unknown headers */
17af0525
AJ
443 hpos = put_header(pb, &ff_asf_head1_guid);
444 put_guid(pb, &ff_asf_head2_guid);
77eb5504
AK
445 avio_wl32(pb, 6);
446 avio_wl16(pb, 0);
542993b0
KA
447 end_header(pb, hpos);
448
449 /* title and other infos */
450 if (has_title) {
cba2f6d5
AK
451 int len;
452 uint8_t *buf;
ae628ec1 453 AVIOContext *dyn_buf;
cba2f6d5 454
b92c5452 455 if (avio_open_dyn_buf(&dyn_buf) < 0)
cba2f6d5
AK
456 return AVERROR(ENOMEM);
457
17af0525 458 hpos = put_header(pb, &ff_asf_comment_header);
cba2f6d5
AK
459
460 for (n = 0; n < FF_ARRAY_ELEMS(tags); n++) {
dccbd97d 461 len = tags[n] ? avio_put_str16le(dyn_buf, tags[n]->value) : 0;
77eb5504 462 avio_wl16(pb, len);
cba2f6d5 463 }
6dc7d80d 464 len = avio_close_dyn_buf(dyn_buf, &buf);
77eb5504 465 avio_write(pb, buf, len);
cba2f6d5 466 av_freep(&buf);
542993b0
KA
467 end_header(pb, hpos);
468 }
488227c5 469 if (metadata_count) {
d2d67e42 470 AVDictionaryEntry *tag = NULL;
17af0525 471 hpos = put_header(pb, &ff_asf_extended_content_header);
77eb5504 472 avio_wl16(pb, metadata_count);
d2d67e42 473 while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
cba2f6d5 474 put_str16(pb, tag->key);
77eb5504 475 avio_wl16(pb, 0);
cba2f6d5 476 put_str16(pb, tag->value);
488227c5
AJ
477 }
478 end_header(pb, hpos);
479 }
bb461370
VP
480 /* chapters using ASF markers */
481 if (!asf->is_streamed && s->nb_chapters) {
482 int ret;
483 if (ret = asf_write_markers(s))
484 return ret;
485 }
542993b0 486 /* stream headers */
48a4ffa7 487 for (n = 0; n < s->nb_streams; n++) {
542993b0
KA
488 int64_t es_pos;
489 // ASFStream *stream = &asf->streams[n];
490
9200514a 491 par = s->streams[n]->codecpar;
542993b0
KA
492 asf->streams[n].num = n + 1;
493 asf->streams[n].seq = 0;
494
9200514a 495 switch (par->codec_type) {
72415b2a 496 case AVMEDIA_TYPE_AUDIO:
542993b0 497 wav_extra_size = 0;
48a4ffa7
DB
498 extra_size = 18 + wav_extra_size;
499 extra_size2 = 8;
542993b0
KA
500 break;
501 default:
72415b2a 502 case AVMEDIA_TYPE_VIDEO:
9200514a 503 wav_extra_size = par->extradata_size;
48a4ffa7
DB
504 extra_size = 0x33 + wav_extra_size;
505 extra_size2 = 0;
542993b0
KA
506 break;
507 }
508
17af0525 509 hpos = put_header(pb, &ff_asf_stream_header);
9200514a 510 if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
17af0525
AJ
511 put_guid(pb, &ff_asf_audio_stream);
512 put_guid(pb, &ff_asf_audio_conceal_spread);
542993b0 513 } else {
17af0525
AJ
514 put_guid(pb, &ff_asf_video_stream);
515 put_guid(pb, &ff_asf_video_conceal_none);
542993b0 516 }
77eb5504 517 avio_wl64(pb, 0); /* ??? */
a2704c97 518 es_pos = avio_tell(pb);
77eb5504
AK
519 avio_wl32(pb, extra_size); /* wav header len */
520 avio_wl32(pb, extra_size2); /* additional data len */
521 avio_wl16(pb, n + 1); /* stream number */
522 avio_wl32(pb, 0); /* ??? */
542993b0 523
9200514a 524 if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
542993b0 525 /* WAVEFORMATEX header */
9200514a 526 int wavsize = ff_put_wav_header(s, pb, par);
542993b0
KA
527
528 if (wavsize < 0)
529 return -1;
530 if (wavsize != extra_size) {
a2704c97 531 cur_pos = avio_tell(pb);
6b4aa5da 532 avio_seek(pb, es_pos, SEEK_SET);
77eb5504 533 avio_wl32(pb, wavsize); /* wav header len */
6b4aa5da 534 avio_seek(pb, cur_pos, SEEK_SET);
542993b0 535 }
982e53fe 536 /* ERROR Correction */
77eb5504 537 avio_w8(pb, 0x01);
9200514a 538 if (par->codec_id == AV_CODEC_ID_ADPCM_G726 || !par->block_align) {
77eb5504
AK
539 avio_wl16(pb, 0x0190);
540 avio_wl16(pb, 0x0190);
48a4ffa7 541 } else {
9200514a
AK
542 avio_wl16(pb, par->block_align);
543 avio_wl16(pb, par->block_align);
1d7d9935 544 }
77eb5504
AK
545 avio_wl16(pb, 0x01);
546 avio_w8(pb, 0x00);
542993b0 547 } else {
9200514a
AK
548 avio_wl32(pb, par->width);
549 avio_wl32(pb, par->height);
77eb5504 550 avio_w8(pb, 2); /* ??? */
9200514a 551 avio_wl16(pb, 40 + par->extradata_size); /* size */
542993b0
KA
552
553 /* BITMAPINFOHEADER header */
9200514a 554 ff_put_bmp_header(pb, par, ff_codec_bmp_tags, 1);
542993b0
KA
555 }
556 end_header(pb, hpos);
557 }
558
559 /* media comments */
560
17af0525
AJ
561 hpos = put_header(pb, &ff_asf_codec_comment_header);
562 put_guid(pb, &ff_asf_codec_comment1_header);
77eb5504 563 avio_wl32(pb, s->nb_streams);
48a4ffa7 564 for (n = 0; n < s->nb_streams; n++) {
6072184e 565 const AVCodecDescriptor *codec_desc;
531d8fa3 566 const char *desc;
542993b0 567
9200514a
AK
568 par = s->streams[n]->codecpar;
569 codec_desc = avcodec_descriptor_get(par->codec_id);
542993b0 570
9200514a 571 if (par->codec_type == AVMEDIA_TYPE_AUDIO)
77eb5504 572 avio_wl16(pb, 2);
9200514a 573 else if (par->codec_type == AVMEDIA_TYPE_VIDEO)
77eb5504 574 avio_wl16(pb, 1);
7205395b 575 else
77eb5504 576 avio_wl16(pb, -1);
7205395b 577
9200514a 578 if (par->codec_id == AV_CODEC_ID_WMAV2)
531d8fa3 579 desc = "Windows Media Audio V8";
7205395b 580 else
6072184e 581 desc = codec_desc ? codec_desc->name : NULL;
cba2f6d5 582
6072184e
AK
583 if (desc) {
584 AVIOContext *dyn_buf;
585 uint8_t *buf;
586 int len;
cba2f6d5 587
6072184e
AK
588 if (avio_open_dyn_buf(&dyn_buf) < 0)
589 return AVERROR(ENOMEM);
cba2f6d5 590
6072184e
AK
591 avio_put_str16le(dyn_buf, desc);
592 len = avio_close_dyn_buf(dyn_buf, &buf);
593 avio_wl16(pb, len / 2); // "number of characters" = length in bytes / 2
594
595 avio_write(pb, buf, len);
596 av_freep(&buf);
597 } else
598 avio_wl16(pb, 0);
cba2f6d5 599
77eb5504 600 avio_wl16(pb, 0); /* no parameters */
115329f1 601
542993b0 602 /* id */
9200514a 603 if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
77eb5504 604 avio_wl16(pb, 2);
9200514a 605 avio_wl16(pb, par->codec_tag);
542993b0 606 } else {
77eb5504 607 avio_wl16(pb, 4);
9200514a 608 avio_wl32(pb, par->codec_tag);
542993b0 609 }
9200514a 610 if (!par->codec_tag)
d65b8230 611 return -1;
542993b0
KA
612 }
613 end_header(pb, hpos);
614
615 /* patch the header size fields */
616
48a4ffa7 617 cur_pos = avio_tell(pb);
542993b0
KA
618 header_size = cur_pos - header_offset;
619 if (asf->is_streamed) {
c53b5dda 620 header_size += 8 + 30 + DATA_HEADER_SIZE;
542993b0 621
6b4aa5da 622 avio_seek(pb, header_offset - 10 - 30, SEEK_SET);
77eb5504 623 avio_wl16(pb, header_size);
6b4aa5da 624 avio_seek(pb, header_offset - 2 - 30, SEEK_SET);
77eb5504 625 avio_wl16(pb, header_size);
542993b0 626
c53b5dda 627 header_size -= 8 + 30 + DATA_HEADER_SIZE;
542993b0
KA
628 }
629 header_size += 24 + 6;
6b4aa5da 630 avio_seek(pb, header_offset - 14, SEEK_SET);
77eb5504 631 avio_wl64(pb, header_size);
6b4aa5da 632 avio_seek(pb, cur_pos, SEEK_SET);
542993b0
KA
633
634 /* movie chunk, followed by packets of packet_size */
635 asf->data_offset = cur_pos;
17af0525 636 put_guid(pb, &ff_asf_data_header);
77eb5504 637 avio_wl64(pb, data_chunk_size);
17af0525 638 put_guid(pb, &ff_asf_my_guid);
77eb5504
AK
639 avio_wl64(pb, asf->nb_packets); /* nb packets */
640 avio_w8(pb, 1); /* ??? */
641 avio_w8(pb, 1); /* ??? */
542993b0
KA
642 return 0;
643}
644
645static int asf_write_header(AVFormatContext *s)
646{
647 ASFContext *asf = s->priv_data;
648
91d19d47 649 s->packet_size = PACKET_SIZE;
542993b0 650 asf->nb_packets = 0;
115329f1 651
48a4ffa7
DB
652 asf->last_indexed_pts = 0;
653 asf->index_ptr = av_malloc(sizeof(ASFIndex) * ASF_INDEX_BLOCK);
982e53fe 654 asf->nb_index_memory_alloc = ASF_INDEX_BLOCK;
48a4ffa7
DB
655 asf->nb_index_count = 0;
656 asf->maximum_packet = 0;
542993b0 657
c53b5dda
VP
658 /* the data-chunk-size has to be 50 (DATA_HEADER_SIZE), which is
659 * data_size - asf->data_offset at the moment this function is done.
660 * It is needed to use asf as a streamable format. */
661 if (asf_write_header1(s, 0, DATA_HEADER_SIZE) < 0) {
542993b0 662 //av_free(asf);
72211a2a 663 av_freep(&asf->index_ptr);
542993b0
KA
664 return -1;
665 }
666
b7f2fdde 667 avio_flush(s->pb);
542993b0 668
48a4ffa7 669 asf->packet_nb_payloads = 0;
542993b0 670 asf->packet_timestamp_start = -1;
48a4ffa7 671 asf->packet_timestamp_end = -1;
e731b8d8 672 ffio_init_context(&asf->pb, asf->packet_buf, s->packet_size, 1,
48a4ffa7 673 NULL, NULL, NULL, NULL);
542993b0
KA
674
675 return 0;
676}
677
678static int asf_write_stream_header(AVFormatContext *s)
679{
680 ASFContext *asf = s->priv_data;
681
682 asf->is_streamed = 1;
683
684 return asf_write_header(s);
685}
686
48a4ffa7
DB
687static int put_payload_parsing_info(AVFormatContext *s,
688 unsigned sendtime, unsigned duration,
689 int nb_payloads, int padsize)
542993b0
KA
690{
691 ASFContext *asf = s->priv_data;
ae628ec1 692 AVIOContext *pb = s->pb;
615b92fd 693 int ppi_size, i;
48a4ffa7 694 int64_t start = avio_tell(pb);
615b92fd
KA
695
696 int iLengthTypeFlags = ASF_PPI_LENGTH_TYPE_FLAGS;
115329f1 697
2d241e66 698 padsize -= PACKET_HEADER_MIN_SIZE;
48a4ffa7 699 if (asf->multi_payloads_present)
2d241e66 700 padsize--;
48a4ffa7 701 assert(padsize >= 0);
2d241e66 702
77eb5504 703 avio_w8(pb, ASF_PACKET_ERROR_CORRECTION_FLAGS);
48a4ffa7 704 for (i = 0; i < ASF_PACKET_ERROR_CORRECTION_DATA_SIZE; i++)
77eb5504 705 avio_w8(pb, 0x0);
542993b0 706
615b92fd
KA
707 if (asf->multi_payloads_present)
708 iLengthTypeFlags |= ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT;
542993b0 709
542993b0
KA
710 if (padsize > 0) {
711 if (padsize < 256)
615b92fd 712 iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE;
542993b0 713 else
615b92fd 714 iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD;
542993b0 715 }
77eb5504 716 avio_w8(pb, iLengthTypeFlags);
615b92fd 717
77eb5504 718 avio_w8(pb, ASF_PPI_PROPERTY_FLAGS);
615b92fd
KA
719
720 if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD)
77eb5504 721 avio_wl16(pb, padsize - 2);
615b92fd 722 if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE)
77eb5504 723 avio_w8(pb, padsize - 1);
615b92fd 724
77eb5504
AK
725 avio_wl32(pb, sendtime);
726 avio_wl16(pb, duration);
615b92fd 727 if (asf->multi_payloads_present)
77eb5504 728 avio_w8(pb, nb_payloads | ASF_PAYLOAD_FLAGS);
615b92fd 729
a2704c97 730 ppi_size = avio_tell(pb) - start;
542993b0 731
615b92fd 732 return ppi_size;
542993b0
KA
733}
734
735static void flush_packet(AVFormatContext *s)
736{
737 ASFContext *asf = s->priv_data;
615b92fd 738 int packet_hdr_size, packet_filled_size;
542993b0 739
a57c41b2
MN
740 assert(asf->packet_timestamp_end >= asf->packet_timestamp_start);
741
48a4ffa7 742 if (asf->is_streamed)
91d19d47 743 put_chunk(s, 0x4424, s->packet_size, 0);
615b92fd 744
48a4ffa7
DB
745 packet_hdr_size = put_payload_parsing_info(s,
746 asf->packet_timestamp_start,
747 asf->packet_timestamp_end -
748 asf->packet_timestamp_start,
749 asf->packet_nb_payloads,
750 asf->packet_size_left);
542993b0 751
2d241e66
MN
752 packet_filled_size = PACKET_SIZE - asf->packet_size_left;
753 assert(packet_hdr_size <= asf->packet_size_left);
615b92fd 754 memset(asf->packet_buf + packet_filled_size, 0, asf->packet_size_left);
542993b0 755
77eb5504 756 avio_write(s->pb, asf->packet_buf, s->packet_size - packet_hdr_size);
542993b0 757
b7f2fdde 758 avio_flush(s->pb);
542993b0 759 asf->nb_packets++;
48a4ffa7 760 asf->packet_nb_payloads = 0;
542993b0 761 asf->packet_timestamp_start = -1;
48a4ffa7 762 asf->packet_timestamp_end = -1;
e731b8d8 763 ffio_init_context(&asf->pb, asf->packet_buf, s->packet_size, 1,
48a4ffa7 764 NULL, NULL, NULL, NULL);
542993b0
KA
765}
766
48a4ffa7
DB
767static void put_payload_header(AVFormatContext *s, ASFStream *stream,
768 int presentation_time, int m_obj_size,
769 int m_obj_offset, int payload_len, int flags)
542993b0
KA
770{
771 ASFContext *asf = s->priv_data;
ae628ec1 772 AVIOContext *pb = &asf->pb;
542993b0 773 int val;
115329f1 774
542993b0 775 val = stream->num;
cc947f04 776 if (flags & AV_PKT_FLAG_KEY)
615b92fd 777 val |= ASF_PL_FLAG_KEY_FRAME;
77eb5504 778 avio_w8(pb, val);
115329f1 779
48a4ffa7
DB
780 avio_w8(pb, stream->seq); // Media object number
781 avio_wl32(pb, m_obj_offset); // Offset Into Media Object
115329f1 782
615b92fd 783 // Replicated Data shall be at least 8 bytes long.
115329f1 784 // The first 4 bytes of data shall contain the
615b92fd 785 // Size of the Media Object that the payload belongs to.
115329f1 786 // The next 4 bytes of data shall contain the
615b92fd 787 // Presentation Time for the media object that the payload belongs to.
77eb5504 788 avio_w8(pb, ASF_PAYLOAD_REPLICATED_DATA_LENGTH);
615b92fd 789
48a4ffa7
DB
790 avio_wl32(pb, m_obj_size); // Replicated Data - Media Object Size
791 avio_wl32(pb, presentation_time); // Replicated Data - Presentation Time
115329f1 792
48a4ffa7
DB
793 if (asf->multi_payloads_present) {
794 avio_wl16(pb, payload_len); // payload length
615b92fd 795 }
542993b0
KA
796}
797
48a4ffa7
DB
798static void put_frame(AVFormatContext *s, ASFStream *stream, AVStream *avst,
799 int timestamp, const uint8_t *buf,
800 int m_obj_size, int flags)
542993b0
KA
801{
802 ASFContext *asf = s->priv_data;
615b92fd
KA
803 int m_obj_offset, payload_len, frag_len1;
804
805 m_obj_offset = 0;
806 while (m_obj_offset < m_obj_size) {
807 payload_len = m_obj_size - m_obj_offset;
808 if (asf->packet_timestamp_start == -1) {
809 asf->multi_payloads_present = (payload_len < MULTI_PAYLOAD_CONSTANT);
115329f1 810
2d241e66 811 asf->packet_size_left = PACKET_SIZE;
48a4ffa7 812 if (asf->multi_payloads_present) {
615b92fd 813 frag_len1 = MULTI_PAYLOAD_CONSTANT - 1;
48a4ffa7 814 } else {
615b92fd
KA
815 frag_len1 = SINGLE_PAYLOAD_DATA_LENGTH;
816 }
190972a0 817 asf->packet_timestamp_start = timestamp;
48a4ffa7 818 } else {
615b92fd 819 // multi payloads
48a4ffa7
DB
820 frag_len1 = asf->packet_size_left -
821 PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS -
822 PACKET_HEADER_MIN_SIZE - 1;
542993b0 823
48a4ffa7 824 if (frag_len1 < payload_len &&
9200514a 825 avst->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
75b213ed
MN
826 flush_packet(s);
827 continue;
828 }
615b92fd 829 }
542993b0 830 if (frag_len1 > 0) {
615b92fd
KA
831 if (payload_len > frag_len1)
832 payload_len = frag_len1;
833 else if (payload_len == (frag_len1 - 1))
48a4ffa7 834 payload_len = frag_len1 - 2; // additional byte need to put padding length
115329f1 835
48a4ffa7
DB
836 put_payload_header(s, stream, timestamp + PREROLL_TIME,
837 m_obj_size, m_obj_offset, payload_len, flags);
77eb5504 838 avio_write(&asf->pb, buf, payload_len);
615b92fd
KA
839
840 if (asf->multi_payloads_present)
841 asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS);
842 else
843 asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD);
542993b0 844 asf->packet_timestamp_end = timestamp;
115329f1 845
615b92fd 846 asf->packet_nb_payloads++;
542993b0 847 } else {
615b92fd 848 payload_len = 0;
542993b0 849 }
615b92fd 850 m_obj_offset += payload_len;
48a4ffa7 851 buf += payload_len;
615b92fd
KA
852
853 if (!asf->multi_payloads_present)
854 flush_packet(s);
2d241e66 855 else if (asf->packet_size_left <= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS + PACKET_HEADER_MIN_SIZE + 1))
542993b0
KA
856 flush_packet(s);
857 }
858 stream->seq++;
859}
860
e928649b 861static int asf_write_packet(AVFormatContext *s, AVPacket *pkt)
542993b0
KA
862{
863 ASFContext *asf = s->priv_data;
09f3c937 864 AVIOContext *pb = s->pb;
542993b0 865 ASFStream *stream;
9200514a 866 AVCodecParameters *par;
48a4ffa7
DB
867 int64_t packet_st, pts;
868 int start_sec, i;
869 int flags = pkt->flags;
09f3c937 870 uint64_t offset = avio_tell(pb);
542993b0 871
9200514a 872 par = s->streams[pkt->stream_index]->codecpar;
e928649b 873 stream = &asf->streams[pkt->stream_index];
542993b0 874
9200514a 875 if (par->codec_type == AVMEDIA_TYPE_AUDIO)
cc947f04 876 flags &= ~AV_PKT_FLAG_KEY;
0d9f8633 877
982e53fe 878 pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts;
9bc93229 879 assert(pts != AV_NOPTS_VALUE);
ff3db937
AK
880
881 if (pts > UINT64_MAX - pkt->duration)
882 return AVERROR(ERANGE);
883 asf->duration = FFMAX(asf->duration, pts + pkt->duration);
542993b0 884
982e53fe 885 packet_st = asf->nb_packets;
48a4ffa7
DB
886 put_frame(s, stream, s->streams[pkt->stream_index],
887 pkt->dts, pkt->data, pkt->size, flags);
982e53fe
C
888
889 /* check index */
cc947f04 890 if ((!asf->is_streamed) && (flags & AV_PKT_FLAG_KEY)) {
ff3db937
AK
891 if (pts / 1000LL > INT_MAX)
892 return AVERROR(ERANGE);
893
894 start_sec = pts / 1000;
895 if (start_sec != asf->last_indexed_pts / 1000) {
48a4ffa7
DB
896 for (i = asf->nb_index_count; i < start_sec; i++) {
897 if (i >= asf->nb_index_memory_alloc) {
f369b935 898 int err;
982e53fe 899 asf->nb_index_memory_alloc += ASF_INDEX_BLOCK;
f369b935
AK
900 if ((err = av_reallocp_array(&asf->index_ptr,
901 asf->nb_index_memory_alloc,
902 sizeof(*asf->index_ptr))) < 0) {
903 asf->nb_index_memory_alloc = 0;
904 return err;
905 }
982e53fe
C
906 }
907 // store
908 asf->index_ptr[i].packet_number = (uint32_t)packet_st;
48a4ffa7 909 asf->index_ptr[i].packet_count = (uint16_t)(asf->nb_packets - packet_st);
09f3c937
VP
910 asf->index_ptr[i].send_time = start_sec * INT64_C(10000000);
911 asf->index_ptr[i].offset = offset;
48a4ffa7
DB
912 asf->maximum_packet = FFMAX(asf->maximum_packet,
913 (uint16_t)(asf->nb_packets - packet_st));
982e53fe 914 }
48a4ffa7 915 asf->nb_index_count = start_sec;
ff3db937 916 asf->last_indexed_pts = pts;
982e53fe
C
917 }
918 }
919 return 0;
920}
921
48a4ffa7
DB
922static int asf_write_index(AVFormatContext *s, ASFIndex *index,
923 uint16_t max, uint32_t count)
982e53fe 924{
ae628ec1 925 AVIOContext *pb = s->pb;
982e53fe
C
926 int i;
927
17af0525 928 put_guid(pb, &ff_asf_simple_index_header);
48a4ffa7 929 avio_wl64(pb, 24 + 16 + 8 + 4 + 4 + (4 + 2) * count);
17af0525 930 put_guid(pb, &ff_asf_my_guid);
77eb5504
AK
931 avio_wl64(pb, ASF_INDEXED_INTERVAL);
932 avio_wl32(pb, max);
933 avio_wl32(pb, count);
48a4ffa7 934 for (i = 0; i < count; i++) {
77eb5504
AK
935 avio_wl32(pb, index[i].packet_number);
936 avio_wl16(pb, index[i].packet_count);
982e53fe
C
937 }
938
542993b0
KA
939 return 0;
940}
941
942static int asf_write_trailer(AVFormatContext *s)
943{
944 ASFContext *asf = s->priv_data;
48a4ffa7 945 int64_t file_size, data_size;
542993b0
KA
946
947 /* flush the current packet */
948 if (asf->pb.buf_ptr > asf->pb.buffer)
949 flush_packet(s);
950
982e53fe 951 /* write index */
a2704c97 952 data_size = avio_tell(s->pb);
48a4ffa7 953 if ((!asf->is_streamed) && (asf->nb_index_count != 0))
982e53fe 954 asf_write_index(s, asf->index_ptr, asf->maximum_packet, asf->nb_index_count);
b7f2fdde 955 avio_flush(s->pb);
982e53fe 956
8978feda 957 if (asf->is_streamed || !s->pb->seekable) {
542993b0
KA
958 put_chunk(s, 0x4524, 0, 0); /* end of stream */
959 } else {
960 /* rewrite an updated header */
a2704c97 961 file_size = avio_tell(s->pb);
6b4aa5da 962 avio_seek(s->pb, 0, SEEK_SET);
982e53fe 963 asf_write_header1(s, file_size, data_size - asf->data_offset);
542993b0
KA
964 }
965
982e53fe 966 av_free(asf->index_ptr);
542993b0
KA
967 return 0;
968}
969
b250f9c6 970#if CONFIG_ASF_MUXER
c6610a21 971AVOutputFormat ff_asf_muxer = {
dfc2c4d9 972 .name = "asf",
0177b7d2 973 .long_name = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
dfc2c4d9
AK
974 .mime_type = "video/x-ms-asf",
975 .extensions = "asf,wmv,wma",
976 .priv_data_size = sizeof(ASFContext),
36ef5369
AK
977 .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_MP2,
978 .video_codec = AV_CODEC_ID_MSMPEG4V3,
dfc2c4d9
AK
979 .write_header = asf_write_header,
980 .write_packet = asf_write_packet,
981 .write_trailer = asf_write_trailer,
20234a4b 982 .flags = AVFMT_GLOBALHEADER,
48a4ffa7 983 .codec_tag = (const AVCodecTag * const []) {
20234a4b
MS
984 codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0
985 },
542993b0 986};
48a4ffa7 987#endif /* CONFIG_ASF_MUXER */
542993b0 988
b250f9c6 989#if CONFIG_ASF_STREAM_MUXER
c6610a21 990AVOutputFormat ff_asf_stream_muxer = {
dfc2c4d9 991 .name = "asf_stream",
0177b7d2 992 .long_name = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
dfc2c4d9
AK
993 .mime_type = "video/x-ms-asf",
994 .extensions = "asf,wmv,wma",
995 .priv_data_size = sizeof(ASFContext),
36ef5369
AK
996 .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_MP2,
997 .video_codec = AV_CODEC_ID_MSMPEG4V3,
dfc2c4d9
AK
998 .write_header = asf_write_stream_header,
999 .write_packet = asf_write_packet,
1000 .write_trailer = asf_write_trailer,
20234a4b 1001 .flags = AVFMT_GLOBALHEADER,
48a4ffa7 1002 .codec_tag = (const AVCodecTag * const []) {
20234a4b
MS
1003 codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0
1004 },
542993b0 1005};
48a4ffa7 1006#endif /* CONFIG_ASF_STREAM_MUXER */