~ubuntu-branches/ubuntu/jaunty/xvidcap/jaunty-proposed

« back to all changes in this revision

Viewing changes to ffmpeg/libavformat/avienc.c

  • Committer: Bazaar Package Importer
  • Author(s): John Dong
  • Date: 2008-02-25 15:47:12 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080225154712-qvr11ekcea4c9ry8
Tags: 1.1.6-0.1ubuntu1
* Merge from debian-multimedia (LP: #120003), Ubuntu Changes:
 - For ffmpeg-related build-deps, remove cvs from package names.
 - Standards-Version 3.7.3
 - Maintainer Spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * AVI encoder.
 
2
 * AVI muxer
3
3
 * Copyright (c) 2000 Fabrice Bellard.
4
4
 *
5
 
 * This library is free software; you can redistribute it and/or
 
5
 * This file is part of FFmpeg.
 
6
 *
 
7
 * FFmpeg is free software; you can redistribute it and/or
6
8
 * modify it under the terms of the GNU Lesser General Public
7
9
 * License as published by the Free Software Foundation; either
8
 
 * version 2 of the License, or (at your option) any later version.
 
10
 * version 2.1 of the License, or (at your option) any later version.
9
11
 *
10
 
 * This library is distributed in the hope that it will be useful,
 
12
 * FFmpeg is distributed in the hope that it will be useful,
11
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
15
 * Lesser General Public License for more details.
14
16
 *
15
17
 * You should have received a copy of the GNU Lesser General Public
16
 
 * License along with this library; if not, write to the Free Software
17
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
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
18
20
 */
19
21
#include "avformat.h"
20
22
#include "avi.h"
 
23
#include "riff.h"
21
24
 
22
25
/*
23
 
 * TODO: 
 
26
 * TODO:
24
27
 *  - fill all fields if non streamed (nb_frames for example)
25
28
 */
26
29
 
 
30
#ifdef CONFIG_AVI_MUXER
27
31
typedef struct AVIIentry {
28
32
    unsigned int flags, pos, len;
29
33
} AVIIentry;
42
46
    offset_t frames_hdr_all, frames_hdr_strm[MAX_STREAMS];
43
47
    int audio_strm_length[MAX_STREAMS];
44
48
    int riff_id;
 
49
    int packet_count[MAX_STREAMS];
45
50
 
46
51
    AVIIndex indexes[MAX_STREAMS];
47
52
} AVIContext;
48
53
 
49
 
static inline AVIIentry* avi_get_ientry(AVIIndex* idx, int ent_id) 
 
54
static inline AVIIentry* avi_get_ientry(AVIIndex* idx, int ent_id)
50
55
{
51
56
    int cl = ent_id / AVI_INDEX_CLUSTER_SIZE;
52
57
    int id = ent_id % AVI_INDEX_CLUSTER_SIZE;
53
58
    return &idx->cluster[cl][id];
54
59
}
55
60
 
56
 
offset_t start_tag(ByteIOContext *pb, const char *tag)
57
 
{
58
 
    put_tag(pb, tag);
59
 
    put_le32(pb, 0);
60
 
    return url_ftell(pb);
61
 
}
62
 
 
63
 
void end_tag(ByteIOContext *pb, offset_t start)
64
 
{
65
 
    offset_t pos;
66
 
 
67
 
    pos = url_ftell(pb);
68
 
    url_fseek(pb, start - 4, SEEK_SET);
69
 
    put_le32(pb, (uint32_t)(pos - start));
70
 
    url_fseek(pb, pos, SEEK_SET);
71
 
}
72
 
 
73
 
/* Note: when encoding, the first matching tag is used, so order is
74
 
   important if multiple tags possible for a given codec. */
75
 
const CodecTag codec_bmp_tags[] = {
76
 
    { CODEC_ID_H263, MKTAG('H', '2', '6', '3') },
77
 
    { CODEC_ID_H263P, MKTAG('H', '2', '6', '3') },
78
 
    { CODEC_ID_H263I, MKTAG('I', '2', '6', '3') }, /* intel h263 */
79
 
 
80
 
    /* added based on MPlayer */
81
 
    { CODEC_ID_H263P, MKTAG('U', '2', '6', '3') },
82
 
    { CODEC_ID_H263P, MKTAG('v', 'i', 'v', '1') },
83
 
 
84
 
    { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X'), .invalid_asf = 1 },
85
 
    { CODEC_ID_MPEG4, MKTAG('D', 'X', '5', '0'), .invalid_asf = 1 },
86
 
    { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D'), .invalid_asf = 1 },
87
 
    { CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') },
88
 
    { CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') },
89
 
    { CODEC_ID_MPEG4, MKTAG(0x04, 0, 0, 0) }, /* some broken avi use this */
90
 
 
91
 
    /* added based on MPlayer */
92
 
    { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', '1') },
93
 
    { CODEC_ID_MPEG4, MKTAG('B', 'L', 'Z', '0') },
94
 
    { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
95
 
    { CODEC_ID_MPEG4, MKTAG('U', 'M', 'P', '4') },
96
 
 
97
 
    { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '3'), .invalid_asf = 1 }, /* default signature when using MSMPEG4 */
98
 
    { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') }, 
99
 
 
100
 
    /* added based on MPlayer */
101
 
    { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', 'G', '3') }, 
102
 
    { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '5') }, 
103
 
    { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '6') }, 
104
 
    { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '4') }, 
105
 
    { CODEC_ID_MSMPEG4V3, MKTAG('A', 'P', '4', '1') }, 
106
 
    { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '1') }, 
107
 
    { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '0') }, 
108
 
 
109
 
    { CODEC_ID_MSMPEG4V2, MKTAG('M', 'P', '4', '2') }, 
110
 
 
111
 
    /* added based on MPlayer */
112
 
    { CODEC_ID_MSMPEG4V2, MKTAG('D', 'I', 'V', '2') },
113
 
 
114
 
    { CODEC_ID_MSMPEG4V1, MKTAG('M', 'P', 'G', '4') }, 
115
 
 
116
 
    /* added based on MPlayer */
117
 
    { CODEC_ID_MSMPEG4V1, MKTAG('D', 'I', 'V', '4') }, 
118
 
 
119
 
    { CODEC_ID_WMV1, MKTAG('W', 'M', 'V', '1') }, 
120
 
 
121
 
    /* added based on MPlayer */
122
 
    { CODEC_ID_WMV2, MKTAG('W', 'M', 'V', '2') }, 
123
 
    { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'd') }, 
124
 
    { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'd') }, 
125
 
    { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'l') }, 
126
 
    { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '2', '5') },
127
 
    { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '1') }, 
128
 
    { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '2') }, 
129
 
    { CODEC_ID_MPEG1VIDEO, MKTAG('P', 'I', 'M', '1') }, 
130
 
    { CODEC_ID_MPEG1VIDEO, MKTAG('V', 'C', 'R', '2') }, 
131
 
    { CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') },
132
 
    { CODEC_ID_MJPEG, MKTAG('L', 'J', 'P', 'G') },
133
 
    { CODEC_ID_LJPEG, MKTAG('L', 'J', 'P', 'G') },
134
 
    { CODEC_ID_MJPEG, MKTAG('J', 'P', 'G', 'L') }, /* Pegasus lossless JPEG */
135
 
    { CODEC_ID_HUFFYUV, MKTAG('H', 'F', 'Y', 'U') },
136
 
    { CODEC_ID_CYUV, MKTAG('C', 'Y', 'U', 'V') },
137
 
    { CODEC_ID_RAWVIDEO, MKTAG('Y', '4', '2', '2') },
138
 
    { CODEC_ID_RAWVIDEO, MKTAG('I', '4', '2', '0') },
139
 
    { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '1') },
140
 
    { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '2') },
141
 
    { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
142
 
    { CODEC_ID_ASV1, MKTAG('A', 'S', 'V', '1') },
143
 
    { CODEC_ID_ASV2, MKTAG('A', 'S', 'V', '2') },
144
 
    { CODEC_ID_VCR1, MKTAG('V', 'C', 'R', '1') },
145
 
    { CODEC_ID_FFV1, MKTAG('F', 'F', 'V', '1') },
146
 
    { CODEC_ID_XAN_WC4, MKTAG('X', 'x', 'a', 'n') },
147
 
    { 0, 0 },
148
 
};
149
 
 
150
 
unsigned int codec_get_tag(const CodecTag *tags, int id)
151
 
{
152
 
    while (tags->id != 0) {
153
 
        if (tags->id == id)
154
 
            return tags->tag;
155
 
        tags++;
156
 
    }
157
 
    return 0;
158
 
}
159
 
 
160
 
static unsigned int codec_get_asf_tag(const CodecTag *tags, int id)
161
 
{
162
 
    while (tags->id != 0) {
163
 
        if (!tags->invalid_asf && tags->id == id)
164
 
            return tags->tag;
165
 
        tags++;
166
 
    }
167
 
    return 0;
168
 
}
169
 
 
170
 
enum CodecID codec_get_id(const CodecTag *tags, unsigned int tag)
171
 
{
172
 
    while (tags->id != 0) {
173
 
        if(   toupper((tag >> 0)&0xFF) == toupper((tags->tag >> 0)&0xFF)
174
 
           && toupper((tag >> 8)&0xFF) == toupper((tags->tag >> 8)&0xFF)
175
 
           && toupper((tag >>16)&0xFF) == toupper((tags->tag >>16)&0xFF)
176
 
           && toupper((tag >>24)&0xFF) == toupper((tags->tag >>24)&0xFF))
177
 
            return tags->id;
178
 
        tags++;
179
 
    }
180
 
    return CODEC_ID_NONE;
181
 
}
182
 
 
183
 
unsigned int codec_get_bmp_tag(int id)
184
 
{
185
 
    return codec_get_tag(codec_bmp_tags, id);
186
 
}
187
 
 
188
 
unsigned int codec_get_wav_tag(int id)
189
 
{
190
 
    return codec_get_tag(codec_wav_tags, id);
191
 
}
192
 
 
193
 
enum CodecID codec_get_bmp_id(unsigned int tag)
194
 
{
195
 
    return codec_get_id(codec_bmp_tags, tag);
196
 
}
197
 
 
198
 
enum CodecID codec_get_wav_id(unsigned int tag)
199
 
{
200
 
    return codec_get_id(codec_wav_tags, tag);
201
 
}
202
 
 
203
 
/* BITMAPINFOHEADER header */
204
 
void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc, const CodecTag *tags, int for_asf)
205
 
{
206
 
    put_le32(pb, 40 + enc->extradata_size); /* size */
207
 
    put_le32(pb, enc->width);
208
 
    put_le32(pb, enc->height);
209
 
    put_le16(pb, 1); /* planes */
210
 
    
211
 
    put_le16(pb, enc->bits_per_sample ? enc->bits_per_sample : 24); /* depth */
212
 
    /* compression type */
213
 
    put_le32(pb, for_asf ? codec_get_asf_tag(tags, enc->codec_id) : enc->codec_tag);
214
 
    put_le32(pb, enc->width * enc->height * 3);
215
 
    put_le32(pb, 0);
216
 
    put_le32(pb, 0);
217
 
    put_le32(pb, 0);
218
 
    put_le32(pb, 0);
219
 
    
220
 
    put_buffer(pb, enc->extradata, enc->extradata_size);
221
 
 
222
 
    if (enc->extradata_size & 1)
223
 
        put_byte(pb, 0);
224
 
}
225
 
 
226
 
static void parse_specific_params(AVCodecContext *stream, int *au_byterate, int *au_ssize, int *au_scale)
227
 
{
228
 
    switch(stream->codec_id) {
229
 
    case CODEC_ID_PCM_S16LE:
230
 
       *au_scale = *au_ssize = 2*stream->channels;
231
 
       *au_byterate = *au_ssize * stream->sample_rate;
232
 
        break;
233
 
    case CODEC_ID_PCM_U8:
234
 
    case CODEC_ID_PCM_ALAW:
235
 
    case CODEC_ID_PCM_MULAW:
236
 
        *au_scale = *au_ssize = stream->channels;
237
 
        *au_byterate = *au_ssize * stream->sample_rate;
238
 
        break;
239
 
    case CODEC_ID_MP2:
240
 
        *au_ssize = 1;
241
 
        *au_scale = 1;
242
 
        *au_byterate = stream->bit_rate / 8;
243
 
    case CODEC_ID_MP3:
244
 
        *au_ssize = 1;
245
 
        *au_scale = 1;
246
 
        *au_byterate = stream->bit_rate / 8;    
247
 
    default:
248
 
        *au_ssize = 1;
249
 
        *au_scale = 1; 
250
 
        *au_byterate = stream->bit_rate / 8;
251
 
        break;
252
 
    }
253
 
}
254
 
 
255
 
static offset_t avi_start_new_riff(AVIContext *avi, ByteIOContext *pb, 
 
61
static offset_t avi_start_new_riff(AVIContext *avi, ByteIOContext *pb,
256
62
                                   const char* riff_tag, const char* list_tag)
257
63
{
258
64
    offset_t loff;
259
65
    int i;
260
 
    
 
66
 
261
67
    avi->riff_id++;
262
68
    for (i=0; i<MAX_STREAMS; i++)
263
69
         avi->indexes[i].entry = 0;
264
 
    
 
70
 
265
71
    avi->riff_start = start_tag(pb, "RIFF");
266
72
    put_tag(pb, riff_tag);
267
73
    loff = start_tag(pb, "LIST");
269
75
    return loff;
270
76
}
271
77
 
272
 
static unsigned char* avi_stream2fourcc(unsigned char* tag, int index, 
273
 
                                        enum CodecType type)
 
78
static char* avi_stream2fourcc(char* tag, int index, enum CodecType type)
274
79
{
275
80
    tag[0] = '0';
276
81
    tag[1] = '0' + index;
285
90
    return tag;
286
91
}
287
92
 
 
93
static void avi_write_info_tag(ByteIOContext *pb, const char *tag, const char *str)
 
94
{
 
95
    int len = strlen(str);
 
96
    if (len > 0) {
 
97
        len++;
 
98
        put_tag(pb, tag);
 
99
        put_le32(pb, len);
 
100
        put_strz(pb, str);
 
101
        if (len & 1)
 
102
            put_byte(pb, 0);
 
103
    }
 
104
}
 
105
 
 
106
static int avi_write_counters(AVFormatContext* s, int riff_id)
 
107
{
 
108
    ByteIOContext *pb = &s->pb;
 
109
    AVIContext *avi = s->priv_data;
 
110
    int n, au_byterate, au_ssize, au_scale, nb_frames = 0;
 
111
    offset_t file_size;
 
112
    AVCodecContext* stream;
 
113
 
 
114
    file_size = url_ftell(pb);
 
115
    for(n = 0; n < s->nb_streams; n++) {
 
116
        assert(avi->frames_hdr_strm[n]);
 
117
        stream = s->streams[n]->codec;
 
118
        url_fseek(pb, avi->frames_hdr_strm[n], SEEK_SET);
 
119
        ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
 
120
        if(au_ssize == 0) {
 
121
            put_le32(pb, avi->packet_count[n]);
 
122
        } else {
 
123
            put_le32(pb, avi->audio_strm_length[n] / au_ssize);
 
124
        }
 
125
        if(stream->codec_type == CODEC_TYPE_VIDEO)
 
126
            nb_frames = FFMAX(nb_frames, avi->packet_count[n]);
 
127
    }
 
128
    if(riff_id == 1) {
 
129
        assert(avi->frames_hdr_all);
 
130
        url_fseek(pb, avi->frames_hdr_all, SEEK_SET);
 
131
        put_le32(pb, nb_frames);
 
132
    }
 
133
    url_fseek(pb, file_size, SEEK_SET);
 
134
 
 
135
    return 0;
 
136
}
 
137
 
288
138
static int avi_write_header(AVFormatContext *s)
289
139
{
290
140
    AVIContext *avi = s->priv_data;
304
154
 
305
155
    video_enc = NULL;
306
156
    for(n=0;n<s->nb_streams;n++) {
307
 
        stream = &s->streams[n]->codec;
 
157
        stream = s->streams[n]->codec;
308
158
        bitrate += stream->bit_rate;
309
159
        if (stream->codec_type == CODEC_TYPE_VIDEO)
310
160
            video_enc = stream;
311
161
    }
312
 
    
 
162
 
313
163
    nb_frames = 0;
314
164
 
315
165
    if(video_enc){
316
 
        put_le32(pb, (uint32_t)(int64_t_C(1000000) * video_enc->frame_rate_base / video_enc->frame_rate));
 
166
        put_le32(pb, (uint32_t)(INT64_C(1000000) * video_enc->time_base.num / video_enc->time_base.den));
317
167
    } else {
318
 
        put_le32(pb, 0);
 
168
        put_le32(pb, 0);
319
169
    }
320
170
    put_le32(pb, bitrate / 8); /* XXX: not quite exact */
321
171
    put_le32(pb, 0); /* padding */
322
 
    put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */
 
172
    if (url_is_streamed(pb))
 
173
        put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED); /* flags */
 
174
    else
 
175
        put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */
323
176
    avi->frames_hdr_all = url_ftell(pb); /* remember this offset to fill later */
324
177
    put_le32(pb, nb_frames); /* nb frames, filled later */
325
178
    put_le32(pb, 0); /* initial frame */
326
179
    put_le32(pb, s->nb_streams); /* nb streams */
327
180
    put_le32(pb, 1024 * 1024); /* suggested buffer size */
328
 
    if(video_enc){    
329
 
    put_le32(pb, video_enc->width);
330
 
    put_le32(pb, video_enc->height);
 
181
    if(video_enc){
 
182
        put_le32(pb, video_enc->width);
 
183
        put_le32(pb, video_enc->height);
331
184
    } else {
332
 
        put_le32(pb, 0);
333
 
        put_le32(pb, 0);
334
 
    }   
335
 
    put_le32(pb, 0); /* reserved */
336
 
    put_le32(pb, 0); /* reserved */
337
 
    put_le32(pb, 0); /* reserved */
338
 
    put_le32(pb, 0); /* reserved */
339
 
    
 
185
        put_le32(pb, 0);
 
186
        put_le32(pb, 0);
 
187
    }
 
188
    put_le32(pb, 0); /* reserved */
 
189
    put_le32(pb, 0); /* reserved */
 
190
    put_le32(pb, 0); /* reserved */
 
191
    put_le32(pb, 0); /* reserved */
 
192
 
340
193
    /* stream list */
341
194
    for(i=0;i<n;i++) {
342
195
        list2 = start_tag(pb, "LIST");
343
196
        put_tag(pb, "strl");
344
 
    
345
 
        stream = &s->streams[i]->codec;
 
197
 
 
198
        stream = s->streams[i]->codec;
346
199
 
347
200
        /* FourCC should really be set by the codec itself */
348
201
        if (! stream->codec_tag) {
352
205
        /* stream generic header */
353
206
        strh = start_tag(pb, "strh");
354
207
        switch(stream->codec_type) {
355
 
        case CODEC_TYPE_VIDEO:
356
 
            put_tag(pb, "vids");
 
208
        case CODEC_TYPE_VIDEO: put_tag(pb, "vids"); break;
 
209
        case CODEC_TYPE_AUDIO: put_tag(pb, "auds"); break;
 
210
//        case CODEC_TYPE_TEXT : put_tag(pb, "txts"); break;
 
211
        case CODEC_TYPE_DATA : put_tag(pb, "dats"); break;
 
212
        }
 
213
        if(stream->codec_type == CODEC_TYPE_VIDEO)
357
214
            put_le32(pb, stream->codec_tag);
358
 
            put_le32(pb, 0); /* flags */
359
 
            put_le16(pb, 0); /* priority */
360
 
            put_le16(pb, 0); /* language */
361
 
            put_le32(pb, 0); /* initial frame */
362
 
            
363
 
            put_le32(pb, stream->frame_rate_base); /* scale */
364
 
            put_le32(pb, stream->frame_rate); /* rate */
365
 
 
366
 
            put_le32(pb, 0); /* start */
367
 
            avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */
368
 
            put_le32(pb, nb_frames); /* length, XXX: fill later */
369
 
            put_le32(pb, 1024 * 1024); /* suggested buffer size */
370
 
            put_le32(pb, -1); /* quality */
371
 
            put_le32(pb, stream->width * stream->height * 3); /* sample size */
372
 
            put_le16(pb, 0);
373
 
            put_le16(pb, 0);
374
 
            put_le16(pb, stream->width);
375
 
            put_le16(pb, stream->height);
376
 
            break;
377
 
        case CODEC_TYPE_AUDIO:
378
 
            put_tag(pb, "auds");
379
 
            put_le32(pb, 1); /* tag */
380
 
            put_le32(pb, 0); /* flags */
381
 
            put_le16(pb, 0); /* priority */
382
 
            put_le16(pb, 0); /* language */
383
 
            put_le32(pb, 0); /* initial frame */
384
 
            parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
385
 
            put_le32(pb, au_scale); /* scale */
386
 
            put_le32(pb, au_byterate); /* rate */
387
 
            put_le32(pb, 0); /* start */
388
 
            avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */
 
215
        else
 
216
            put_le32(pb, 1);
 
217
        put_le32(pb, 0); /* flags */
 
218
        put_le16(pb, 0); /* priority */
 
219
        put_le16(pb, 0); /* language */
 
220
        put_le32(pb, 0); /* initial frame */
 
221
 
 
222
        ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
 
223
 
 
224
        put_le32(pb, au_scale); /* scale */
 
225
        put_le32(pb, au_byterate); /* rate */
 
226
        av_set_pts_info(s->streams[i], 64, au_scale, au_byterate);
 
227
 
 
228
        put_le32(pb, 0); /* start */
 
229
        avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */
 
230
        if (url_is_streamed(pb))
 
231
            put_le32(pb, AVI_MAX_RIFF_SIZE); /* FIXME: this may be broken, but who cares */
 
232
        else
389
233
            put_le32(pb, 0); /* length, XXX: filled later */
390
 
            put_le32(pb, 12 * 1024); /* suggested buffer size */
391
 
            put_le32(pb, -1); /* quality */
392
 
            put_le32(pb, au_ssize); /* sample size */
393
 
            put_le32(pb, 0);
394
 
            put_le32(pb, 0);
395
 
            break;
396
 
        default:
397
 
            av_abort();
398
 
        }
 
234
 
 
235
        /* suggested buffer size */ //FIXME set at the end to largest chunk
 
236
        if(stream->codec_type == CODEC_TYPE_VIDEO)
 
237
            put_le32(pb, 1024 * 1024);
 
238
        else if(stream->codec_type == CODEC_TYPE_AUDIO)
 
239
            put_le32(pb, 12 * 1024);
 
240
        else
 
241
            put_le32(pb, 0);
 
242
        put_le32(pb, -1); /* quality */
 
243
        put_le32(pb, au_ssize); /* sample size */
 
244
        put_le32(pb, 0);
 
245
        put_le16(pb, stream->width);
 
246
        put_le16(pb, stream->height);
399
247
        end_tag(pb, strh);
400
248
 
 
249
      if(stream->codec_type != CODEC_TYPE_DATA){
401
250
        strf = start_tag(pb, "strf");
402
251
        switch(stream->codec_type) {
403
252
        case CODEC_TYPE_VIDEO:
404
 
            put_bmp_header(pb, stream, codec_bmp_tags, 0);
 
253
            put_bmp_header(pb, stream, codec_bmp_tags, 0);
405
254
            break;
406
255
        case CODEC_TYPE_AUDIO:
407
256
            if (put_wav_header(pb, stream) < 0) {
410
259
            }
411
260
            break;
412
261
        default:
413
 
            av_abort();
 
262
            return -1;
414
263
        }
415
264
        end_tag(pb, strf);
416
 
        
417
 
        if (!url_is_streamed(pb)) {
418
 
            unsigned char tag[5];
419
 
            int j;
420
 
    
421
 
            /* Starting to lay out AVI OpenDML master index. 
422
 
             * We want to make it JUNK entry for now, since we'd
423
 
             * like to get away without making AVI an OpenDML one 
424
 
             * for compatibility reasons.
425
 
             */
426
 
            avi->indexes[i].entry = avi->indexes[i].ents_allocated = 0;
427
 
            avi->indexes[i].indx_start = start_tag(pb, "JUNK"); 
428
 
            put_le16(pb, 4);        /* wLongsPerEntry */
429
 
            put_byte(pb, 0);        /* bIndexSubType (0 == frame index) */
430
 
            put_byte(pb, 0);        /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */
431
 
            put_le32(pb, 0);        /* nEntriesInUse (will fill out later on) */
432
 
            put_tag(pb, avi_stream2fourcc(&tag[0], i, stream->codec_type));
433
 
                                    /* dwChunkId */
434
 
            put_le64(pb, 0);        /* dwReserved[3]
435
 
            put_le32(pb, 0);           Must be 0.    */
436
 
            for (j=0; j < AVI_MASTER_INDEX_SIZE * 2; j++)
437
 
                 put_le64(pb, 0);
438
 
            end_tag(pb, avi->indexes[i].indx_start);
439
 
        }
440
 
        
 
265
      }
 
266
 
 
267
        if (!url_is_streamed(pb)) {
 
268
            unsigned char tag[5];
 
269
            int j;
 
270
 
 
271
            /* Starting to lay out AVI OpenDML master index.
 
272
             * We want to make it JUNK entry for now, since we'd
 
273
             * like to get away without making AVI an OpenDML one
 
274
             * for compatibility reasons.
 
275
             */
 
276
            avi->indexes[i].entry = avi->indexes[i].ents_allocated = 0;
 
277
            avi->indexes[i].indx_start = start_tag(pb, "JUNK");
 
278
            put_le16(pb, 4);        /* wLongsPerEntry */
 
279
            put_byte(pb, 0);        /* bIndexSubType (0 == frame index) */
 
280
            put_byte(pb, 0);        /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */
 
281
            put_le32(pb, 0);        /* nEntriesInUse (will fill out later on) */
 
282
            put_tag(pb, avi_stream2fourcc(&tag[0], i, stream->codec_type));
 
283
                                    /* dwChunkId */
 
284
            put_le64(pb, 0);        /* dwReserved[3]
 
285
            put_le32(pb, 0);           Must be 0.    */
 
286
            for (j=0; j < AVI_MASTER_INDEX_SIZE * 2; j++)
 
287
                 put_le64(pb, 0);
 
288
            end_tag(pb, avi->indexes[i].indx_start);
 
289
        }
 
290
 
441
291
        end_tag(pb, list2);
442
292
    }
443
 
    
 
293
 
444
294
    if (!url_is_streamed(pb)) {
445
295
        /* AVI could become an OpenDML one, if it grows beyond 2Gb range */
446
296
        avi->odml_list = start_tag(pb, "JUNK");
453
303
    }
454
304
 
455
305
    end_tag(pb, list1);
456
 
    
 
306
 
 
307
    list2 = start_tag(pb, "LIST");
 
308
    put_tag(pb, "INFO");
 
309
    avi_write_info_tag(pb, "INAM", s->title);
 
310
    avi_write_info_tag(pb, "IART", s->author);
 
311
    avi_write_info_tag(pb, "ICOP", s->copyright);
 
312
    avi_write_info_tag(pb, "ICMT", s->comment);
 
313
    avi_write_info_tag(pb, "IPRD", s->album);
 
314
    avi_write_info_tag(pb, "IGNR", s->genre);
 
315
    if (s->track) {
 
316
        char str_track[4];
 
317
        snprintf(str_track, 4, "%d", s->track);
 
318
        avi_write_info_tag(pb, "IPRT", str_track);
 
319
    }
 
320
    if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT))
 
321
        avi_write_info_tag(pb, "ISFT", LIBAVFORMAT_IDENT);
 
322
    end_tag(pb, list2);
 
323
 
 
324
    /* some padding for easier tag editing */
 
325
    list2 = start_tag(pb, "JUNK");
 
326
    for (i = 0; i < 1016; i += 4)
 
327
        put_le32(pb, 0);
 
328
    end_tag(pb, list2);
 
329
 
457
330
    avi->movi_list = start_tag(pb, "LIST");
458
331
    put_tag(pb, "movi");
459
332
 
466
339
{
467
340
    ByteIOContext *pb = &s->pb;
468
341
    AVIContext *avi = s->priv_data;
469
 
    unsigned char tag[5];
470
 
    unsigned char ix_tag[] = "ix00";
 
342
    char tag[5];
 
343
    char ix_tag[] = "ix00";
471
344
    int i, j;
472
 
    
 
345
 
 
346
    assert(!url_is_streamed(pb));
 
347
 
473
348
    if (avi->riff_id > AVI_MASTER_INDEX_SIZE)
474
349
        return -1;
475
 
    
 
350
 
476
351
    for (i=0;i<s->nb_streams;i++) {
477
 
         offset_t ix, pos;
478
 
         
479
 
         avi_stream2fourcc(&tag[0], i, s->streams[i]->codec.codec_type);
480
 
         ix_tag[3] = '0' + i;
481
 
         
482
 
         /* Writing AVI OpenDML leaf index chunk */
483
 
         ix = url_ftell(pb); 
484
 
         put_tag(pb, &ix_tag[0]);     /* ix?? */
485
 
         put_le32(pb, avi->indexes[i].entry * 8 + 24); 
486
 
                                      /* chunk size */
 
352
         offset_t ix, pos;
 
353
 
 
354
         avi_stream2fourcc(&tag[0], i, s->streams[i]->codec->codec_type);
 
355
         ix_tag[3] = '0' + i;
 
356
 
 
357
         /* Writing AVI OpenDML leaf index chunk */
 
358
         ix = url_ftell(pb);
 
359
         put_tag(pb, &ix_tag[0]);     /* ix?? */
 
360
         put_le32(pb, avi->indexes[i].entry * 8 + 24);
 
361
                                      /* chunk size */
487
362
         put_le16(pb, 2);             /* wLongsPerEntry */
488
 
         put_byte(pb, 0);             /* bIndexSubType (0 == frame index) */ 
489
 
         put_byte(pb, 1);             /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */
490
 
         put_le32(pb, avi->indexes[i].entry);          
491
 
                                      /* nEntriesInUse */
492
 
         put_tag(pb, &tag[0]);        /* dwChunkId */
493
 
         put_le64(pb, avi->movi_list);/* qwBaseOffset */
494
 
         put_le32(pb, 0);             /* dwReserved_3 (must be 0) */
 
363
         put_byte(pb, 0);             /* bIndexSubType (0 == frame index) */
 
364
         put_byte(pb, 1);             /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */
 
365
         put_le32(pb, avi->indexes[i].entry);
 
366
                                      /* nEntriesInUse */
 
367
         put_tag(pb, &tag[0]);        /* dwChunkId */
 
368
         put_le64(pb, avi->movi_list);/* qwBaseOffset */
 
369
         put_le32(pb, 0);             /* dwReserved_3 (must be 0) */
495
370
 
496
371
         for (j=0; j<avi->indexes[i].entry; j++) {
497
372
             AVIIentry* ie = avi_get_ientry(&avi->indexes[i], j);
498
 
             put_le32(pb, ie->pos + 8);
499
 
             put_le32(pb, ((uint32_t)ie->len & ~0x80000000) |
500
 
                          (ie->flags & 0x10 ? 0 : 0x80000000));
 
373
             put_le32(pb, ie->pos + 8);
 
374
             put_le32(pb, ((uint32_t)ie->len & ~0x80000000) |
 
375
                          (ie->flags & 0x10 ? 0 : 0x80000000));
501
376
         }
502
 
         put_flush_packet(pb);
 
377
         put_flush_packet(pb);
503
378
         pos = url_ftell(pb);
504
 
        
505
 
         /* Updating one entry in the AVI OpenDML master index */
506
 
         url_fseek(pb, avi->indexes[i].indx_start - 8, SEEK_SET);
507
 
         put_tag(pb, "indx");                 /* enabling this entry */
508
 
         url_fskip(pb, 8);
509
 
         put_le32(pb, avi->riff_id);          /* nEntriesInUse */
510
 
         url_fskip(pb, 16*avi->riff_id);
511
 
         put_le64(pb, ix);                    /* qwOffset */
512
 
         put_le32(pb, pos - ix);              /* dwSize */
513
 
         put_le32(pb, avi->indexes[i].entry); /* dwDuration */
514
 
 
515
 
         url_fseek(pb, pos, SEEK_SET);
 
379
 
 
380
         /* Updating one entry in the AVI OpenDML master index */
 
381
         url_fseek(pb, avi->indexes[i].indx_start - 8, SEEK_SET);
 
382
         put_tag(pb, "indx");                 /* enabling this entry */
 
383
         url_fskip(pb, 8);
 
384
         put_le32(pb, avi->riff_id);          /* nEntriesInUse */
 
385
         url_fskip(pb, 16*avi->riff_id);
 
386
         put_le64(pb, ix);                    /* qwOffset */
 
387
         put_le32(pb, pos - ix);              /* dwSize */
 
388
         put_le32(pb, avi->indexes[i].entry); /* dwDuration */
 
389
 
 
390
         url_fseek(pb, pos, SEEK_SET);
516
391
    }
517
392
    return 0;
518
393
}
521
396
{
522
397
    ByteIOContext *pb = &s->pb;
523
398
    AVIContext *avi = s->priv_data;
524
 
    offset_t file_size, idx_chunk;
525
 
    int i, n, nb_frames, au_byterate, au_ssize, au_scale;
526
 
    AVCodecContext *stream;
527
 
    unsigned char tag[5];
 
399
    offset_t idx_chunk;
 
400
    int i;
 
401
    char tag[5];
528
402
 
529
403
    if (!url_is_streamed(pb)) {
530
 
        AVIIentry* ie = 0, *tie;
531
 
        int entry[MAX_STREAMS];
532
 
        int empty, stream_id = -1;
533
 
 
534
 
        idx_chunk = start_tag(pb, "idx1");
535
 
        memset(&entry[0], 0, sizeof(entry));
536
 
        do {
537
 
            empty = 1;
538
 
            for (i=0; i<s->nb_streams; i++) {
539
 
                 if (avi->indexes[i].entry <= entry[i])
540
 
                     continue;
541
 
                 
542
 
                 tie = avi_get_ientry(&avi->indexes[i], entry[i]);
543
 
                 if (empty || tie->pos < ie->pos) {
544
 
                     ie = tie; 
545
 
                     stream_id = i;
546
 
                 }
547
 
                 empty = 0;
548
 
            }
549
 
            if (!empty) {
550
 
                avi_stream2fourcc(&tag[0], stream_id, 
551
 
                                  s->streams[stream_id]->codec.codec_type); 
552
 
                put_tag(pb, &tag[0]);
553
 
                put_le32(pb, ie->flags);
 
404
        AVIIentry* ie = 0, *tie;
 
405
        int entry[MAX_STREAMS];
 
406
        int empty, stream_id = -1;
 
407
 
 
408
        idx_chunk = start_tag(pb, "idx1");
 
409
        memset(&entry[0], 0, sizeof(entry));
 
410
        do {
 
411
            empty = 1;
 
412
            for (i=0; i<s->nb_streams; i++) {
 
413
                 if (avi->indexes[i].entry <= entry[i])
 
414
                     continue;
 
415
 
 
416
                 tie = avi_get_ientry(&avi->indexes[i], entry[i]);
 
417
                 if (empty || tie->pos < ie->pos) {
 
418
                     ie = tie;
 
419
                     stream_id = i;
 
420
                 }
 
421
                 empty = 0;
 
422
            }
 
423
            if (!empty) {
 
424
                avi_stream2fourcc(&tag[0], stream_id,
 
425
                                  s->streams[stream_id]->codec->codec_type);
 
426
                put_tag(pb, &tag[0]);
 
427
                put_le32(pb, ie->flags);
554
428
                put_le32(pb, ie->pos);
555
429
                put_le32(pb, ie->len);
556
 
                entry[stream_id]++;
557
 
            }
558
 
        } while (!empty);
559
 
        end_tag(pb, idx_chunk);
560
 
 
561
 
        /* Fill in frame/sample counters */
562
 
        file_size = url_ftell(pb);
563
 
        nb_frames = 0;
564
 
        for(n=0;n<s->nb_streams;n++) {
565
 
            if (avi->frames_hdr_strm[n] != 0) {
566
 
                stream = &s->streams[n]->codec;
567
 
                url_fseek(pb, avi->frames_hdr_strm[n], SEEK_SET);
568
 
                if (stream->codec_type == CODEC_TYPE_VIDEO) {
569
 
                    put_le32(pb, stream->frame_number); 
570
 
                    if (nb_frames < stream->frame_number)
571
 
                        nb_frames = stream->frame_number;
572
 
                } else {
573
 
                    if (stream->codec_id == CODEC_ID_MP2 || stream->codec_id == CODEC_ID_MP3) {
574
 
                        put_le32(pb, stream->frame_number);
575
 
                        nb_frames += stream->frame_number;
576
 
                    } else {
577
 
                        parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
578
 
                        put_le32(pb, avi->audio_strm_length[n] / au_ssize);
579
 
                    }
580
 
                }
 
430
                entry[stream_id]++;
581
431
            }
582
 
       }
583
 
       if (avi->frames_hdr_all != 0) {
584
 
           url_fseek(pb, avi->frames_hdr_all, SEEK_SET);
585
 
           put_le32(pb, nb_frames); 
586
 
       }
587
 
       url_fseek(pb, file_size, SEEK_SET);
 
432
        } while (!empty);
 
433
        end_tag(pb, idx_chunk);
 
434
 
 
435
        avi_write_counters(s, avi->riff_id);
588
436
    }
589
437
    return 0;
590
438
}
591
439
 
592
 
static int avi_write_packet(AVFormatContext *s, int stream_index,
593
 
                            const uint8_t *buf, int size, int64_t pts)
 
440
static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
594
441
{
595
442
    AVIContext *avi = s->priv_data;
596
443
    ByteIOContext *pb = &s->pb;
597
444
    unsigned char tag[5];
598
 
    unsigned int flags;
599
 
    AVCodecContext *enc;
600
 
 
601
 
    if (url_ftell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE) { 
 
445
    unsigned int flags=0;
 
446
    const int stream_index= pkt->stream_index;
 
447
    AVCodecContext *enc= s->streams[stream_index]->codec;
 
448
    int size= pkt->size;
 
449
 
 
450
//    av_log(s, AV_LOG_DEBUG, "%"PRId64" %d %d\n", pkt->dts, avi->packet_count[stream_index], stream_index);
 
451
    while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avi->packet_count[stream_index]){
 
452
        AVPacket empty_packet;
 
453
 
 
454
        av_init_packet(&empty_packet);
 
455
        empty_packet.size= 0;
 
456
        empty_packet.data= NULL;
 
457
        empty_packet.stream_index= stream_index;
 
458
        avi_write_packet(s, &empty_packet);
 
459
//        av_log(s, AV_LOG_DEBUG, "dup %"PRId64" %d\n", pkt->dts, avi->packet_count[stream_index]);
 
460
    }
 
461
    avi->packet_count[stream_index]++;
 
462
 
 
463
    // Make sure to put an OpenDML chunk when the file size exceeds the limits
 
464
    if (!url_is_streamed(pb) &&
 
465
        (url_ftell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) {
 
466
 
602
467
        avi_write_ix(s);
603
468
        end_tag(pb, avi->movi_list);
604
 
        
605
 
        if (avi->riff_id == 1)
606
 
            avi_write_idx1(s);
607
 
 
608
 
        end_tag(pb, avi->riff_start);
609
 
        avi->movi_list = avi_start_new_riff(avi, pb, "AVIX", "movi");
 
469
 
 
470
        if (avi->riff_id == 1)
 
471
            avi_write_idx1(s);
 
472
 
 
473
        end_tag(pb, avi->riff_start);
 
474
        avi->movi_list = avi_start_new_riff(avi, pb, "AVIX", "movi");
610
475
    }
611
 
    
612
 
    enc = &s->streams[stream_index]->codec;
 
476
 
613
477
    avi_stream2fourcc(&tag[0], stream_index, enc->codec_type);
 
478
    if(pkt->flags&PKT_FLAG_KEY)
 
479
        flags = 0x10;
614
480
    if (enc->codec_type == CODEC_TYPE_AUDIO) {
615
481
       avi->audio_strm_length[stream_index] += size;
616
 
       flags = 0x10;
617
 
    } else
618
 
       flags = enc->coded_frame->key_frame ? 0x10 : 0x00;
 
482
    }
619
483
 
620
484
    if (!url_is_streamed(&s->pb)) {
621
485
        AVIIndex* idx = &avi->indexes[stream_index];
622
 
        int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE;
623
 
        int id = idx->entry % AVI_INDEX_CLUSTER_SIZE;
 
486
        int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE;
 
487
        int id = idx->entry % AVI_INDEX_CLUSTER_SIZE;
624
488
        if (idx->ents_allocated <= idx->entry) {
625
 
            idx->cluster = av_realloc(idx->cluster, (cl+1)*sizeof(void*)); 
626
 
            if (!idx->cluster)
627
 
                return -1;
 
489
            idx->cluster = av_realloc(idx->cluster, (cl+1)*sizeof(void*));
 
490
            if (!idx->cluster)
 
491
                return -1;
628
492
            idx->cluster[cl] = av_malloc(AVI_INDEX_CLUSTER_SIZE*sizeof(AVIIentry));
629
 
            if (!idx->cluster[cl])
630
 
                return -1;
631
 
            idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE;
632
 
        }
633
 
        
634
 
        idx->cluster[cl][id].flags = flags; 
 
493
            if (!idx->cluster[cl])
 
494
                return -1;
 
495
            idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE;
 
496
        }
 
497
 
 
498
        idx->cluster[cl][id].flags = flags;
635
499
        idx->cluster[cl][id].pos = url_ftell(pb) - avi->movi_list;
636
500
        idx->cluster[cl][id].len = size;
637
 
        idx->entry++;
 
501
        idx->entry++;
638
502
    }
639
 
    
 
503
 
640
504
    put_buffer(pb, tag, 4);
641
505
    put_le32(pb, size);
642
 
    put_buffer(pb, buf, size);
 
506
    put_buffer(pb, pkt->data, size);
643
507
    if (size & 1)
644
508
        put_byte(pb, 0);
645
509
 
655
519
    int i, j, n, nb_frames;
656
520
    offset_t file_size;
657
521
 
658
 
    if (avi->riff_id == 1) {
659
 
        end_tag(pb, avi->movi_list);
660
 
        res = avi_write_idx1(s);
661
 
        end_tag(pb, avi->riff_start);
662
 
    } else {
663
 
        avi_write_ix(s);
664
 
        end_tag(pb, avi->movi_list);
665
 
        end_tag(pb, avi->riff_start);
666
 
 
667
 
        file_size = url_ftell(pb);
668
 
        url_fseek(pb, avi->odml_list - 8, SEEK_SET);
669
 
        put_tag(pb, "LIST"); /* Making this AVI OpenDML one */
670
 
        url_fskip(pb, 16);
671
 
 
672
 
        for (n=nb_frames=0;n<s->nb_streams;n++) {
673
 
             AVCodecContext *stream = &s->streams[n]->codec;
674
 
             if (stream->codec_type == CODEC_TYPE_VIDEO) {
675
 
                 if (nb_frames < stream->frame_number)
676
 
                     nb_frames = stream->frame_number;
677
 
             } else {
678
 
                 if (stream->codec_id == CODEC_ID_MP2 || stream->codec_id == CODEC_ID_MP3) {
679
 
                     nb_frames += stream->frame_number;
 
522
    if (!url_is_streamed(pb)){
 
523
        if (avi->riff_id == 1) {
 
524
            end_tag(pb, avi->movi_list);
 
525
            res = avi_write_idx1(s);
 
526
            end_tag(pb, avi->riff_start);
 
527
        } else {
 
528
            avi_write_ix(s);
 
529
            end_tag(pb, avi->movi_list);
 
530
            end_tag(pb, avi->riff_start);
 
531
 
 
532
            file_size = url_ftell(pb);
 
533
            url_fseek(pb, avi->odml_list - 8, SEEK_SET);
 
534
            put_tag(pb, "LIST"); /* Making this AVI OpenDML one */
 
535
            url_fskip(pb, 16);
 
536
 
 
537
            for (n=nb_frames=0;n<s->nb_streams;n++) {
 
538
                AVCodecContext *stream = s->streams[n]->codec;
 
539
                if (stream->codec_type == CODEC_TYPE_VIDEO) {
 
540
                    if (nb_frames < avi->packet_count[n])
 
541
                        nb_frames = avi->packet_count[n];
 
542
                } else {
 
543
                    if (stream->codec_id == CODEC_ID_MP2 || stream->codec_id == CODEC_ID_MP3) {
 
544
                        nb_frames += avi->packet_count[n];
 
545
                    }
680
546
                }
681
547
            }
 
548
            put_le32(pb, nb_frames);
 
549
            url_fseek(pb, file_size, SEEK_SET);
 
550
 
 
551
            avi_write_counters(s, avi->riff_id);
682
552
        }
683
 
        put_le32(pb, nb_frames);
684
 
        url_fseek(pb, file_size, SEEK_SET);
685
553
    }
686
554
    put_flush_packet(pb);
687
555
 
688
556
    for (i=0; i<MAX_STREAMS; i++) {
689
 
         for (j=0; j<avi->indexes[i].ents_allocated/AVI_INDEX_CLUSTER_SIZE; j++)
 
557
         for (j=0; j<avi->indexes[i].ents_allocated/AVI_INDEX_CLUSTER_SIZE; j++)
690
558
              av_free(avi->indexes[i].cluster[j]);
691
 
         av_free(avi->indexes[i].cluster);
692
 
         avi->indexes[i].cluster = NULL;
693
 
         avi->indexes[i].ents_allocated = avi->indexes[i].entry = 0;
 
559
         av_free(avi->indexes[i].cluster);
 
560
         avi->indexes[i].cluster = NULL;
 
561
         avi->indexes[i].ents_allocated = avi->indexes[i].entry = 0;
694
562
    }
695
 
    
 
563
 
696
564
    return res;
697
565
}
698
566
 
699
 
static AVOutputFormat avi_oformat = {
 
567
AVOutputFormat avi_muxer = {
700
568
    "avi",
701
569
    "avi format",
702
570
    "video/x-msvideo",
707
575
    avi_write_header,
708
576
    avi_write_packet,
709
577
    avi_write_trailer,
 
578
    .codec_tag= (const AVCodecTag*[]){codec_bmp_tags, codec_wav_tags, 0},
710
579
};
711
 
 
712
 
int avienc_init(void)
713
 
{
714
 
    av_register_output_format(&avi_oformat);
715
 
    return 0;
716
 
}
 
580
#endif //CONFIG_AVI_MUXER