Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/*
2
 * RIFF muxing functions
3
 * Copyright (c) 2000 Fabrice Bellard
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
 
22
#include "libavutil/dict.h"
23
#include "libavutil/log.h"
24
#include "libavutil/mathematics.h"
25
#include "libavcodec/avcodec.h"
26
#include "libavcodec/bytestream.h"
27
#include "avformat.h"
28
#include "avio_internal.h"
29
#include "riff.h"
30
 
31
int64_t ff_start_tag(AVIOContext *pb, const char *tag)
32
{
33
    ffio_wfourcc(pb, tag);
34
    avio_wl32(pb, 0);
35
    return avio_tell(pb);
36
}
37
 
38
void ff_end_tag(AVIOContext *pb, int64_t start)
39
{
40
    int64_t pos;
41
 
42
    av_assert0((start&1) == 0);
43
 
44
    pos = avio_tell(pb);
45
    if (pos & 1)
46
        avio_w8(pb, 0);
47
    avio_seek(pb, start - 4, SEEK_SET);
48
    avio_wl32(pb, (uint32_t)(pos - start));
49
    avio_seek(pb, FFALIGN(pos, 2), SEEK_SET);
50
}
51
 
52
/* WAVEFORMATEX header */
53
/* returns the size or -1 on error */
54
int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc)
55
{
56
    int bps, blkalign, bytespersec, frame_size;
57
    int hdrsize = 18;
58
    int waveformatextensible;
59
    uint8_t temp[256];
60
    uint8_t *riff_extradata       = temp;
61
    uint8_t *riff_extradata_start = temp;
62
 
63
    if (!enc->codec_tag || enc->codec_tag > 0xffff)
64
        return -1;
65
 
66
    /* We use the known constant frame size for the codec if known, otherwise
67
     * fall back on using AVCodecContext.frame_size, which is not as reliable
68
     * for indicating packet duration. */
69
    frame_size = av_get_audio_frame_duration(enc, 0);
70
    if (!frame_size)
71
        frame_size = enc->frame_size;
72
 
73
    waveformatextensible = (enc->channels > 2 && enc->channel_layout) ||
74
                           enc->sample_rate > 48000 ||
75
                           av_get_bits_per_sample(enc->codec_id) > 16;
76
 
77
    if (waveformatextensible)
78
        avio_wl16(pb, 0xfffe);
79
    else
80
        avio_wl16(pb, enc->codec_tag);
81
 
82
    avio_wl16(pb, enc->channels);
83
    avio_wl32(pb, enc->sample_rate);
84
    if (enc->codec_id == AV_CODEC_ID_ATRAC3 ||
85
        enc->codec_id == AV_CODEC_ID_G723_1 ||
86
        enc->codec_id == AV_CODEC_ID_MP2    ||
87
        enc->codec_id == AV_CODEC_ID_MP3    ||
88
        enc->codec_id == AV_CODEC_ID_GSM_MS) {
89
        bps = 0;
90
    } else {
91
        if (!(bps = av_get_bits_per_sample(enc->codec_id))) {
92
            if (enc->bits_per_coded_sample)
93
                bps = enc->bits_per_coded_sample;
94
            else
95
                bps = 16;  // default to 16
96
        }
97
    }
98
    if (bps != enc->bits_per_coded_sample && enc->bits_per_coded_sample) {
99
        av_log(enc, AV_LOG_WARNING,
100
               "requested bits_per_coded_sample (%d) "
101
               "and actually stored (%d) differ\n",
102
               enc->bits_per_coded_sample, bps);
103
    }
104
 
105
    if (enc->codec_id == AV_CODEC_ID_MP2 ||
106
        enc->codec_id == AV_CODEC_ID_MP3) {
107
        /* This is wrong, but it seems many demuxers do not work if this
108
         * is set correctly. */
109
        blkalign = frame_size;
110
        // blkalign = 144 * enc->bit_rate/enc->sample_rate;
111
    } else if (enc->codec_id == AV_CODEC_ID_AC3) {
112
        blkalign = 3840;                /* maximum bytes per frame */
113
    } else if (enc->codec_id == AV_CODEC_ID_AAC) {
114
        blkalign = 768 * enc->channels; /* maximum bytes per frame */
115
    } else if (enc->codec_id == AV_CODEC_ID_G723_1) {
116
        blkalign = 24;
117
    } else if (enc->block_align != 0) { /* specified by the codec */
118
        blkalign = enc->block_align;
119
    } else
120
        blkalign = bps * enc->channels / av_gcd(8, bps);
121
    if (enc->codec_id == AV_CODEC_ID_PCM_U8 ||
122
        enc->codec_id == AV_CODEC_ID_PCM_S24LE ||
123
        enc->codec_id == AV_CODEC_ID_PCM_S32LE ||
124
        enc->codec_id == AV_CODEC_ID_PCM_F32LE ||
125
        enc->codec_id == AV_CODEC_ID_PCM_F64LE ||
126
        enc->codec_id == AV_CODEC_ID_PCM_S16LE) {
127
        bytespersec = enc->sample_rate * blkalign;
128
    } else if (enc->codec_id == AV_CODEC_ID_G723_1) {
129
        bytespersec = 800;
130
    } else {
131
        bytespersec = enc->bit_rate / 8;
132
    }
133
    avio_wl32(pb, bytespersec); /* bytes per second */
134
    avio_wl16(pb, blkalign);    /* block align */
135
    avio_wl16(pb, bps);         /* bits per sample */
136
    if (enc->codec_id == AV_CODEC_ID_MP3) {
137
        hdrsize += 12;
138
        bytestream_put_le16(&riff_extradata, 1);    /* wID */
139
        bytestream_put_le32(&riff_extradata, 2);    /* fdwFlags */
140
        bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */
141
        bytestream_put_le16(&riff_extradata, 1);    /* nFramesPerBlock */
142
        bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */
143
    } else if (enc->codec_id == AV_CODEC_ID_MP2) {
144
        hdrsize += 22;
145
        /* fwHeadLayer */
146
        bytestream_put_le16(&riff_extradata, 2);
147
        /* dwHeadBitrate */
148
        bytestream_put_le32(&riff_extradata, enc->bit_rate);
149
        /* fwHeadMode */
150
        bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8);
151
        /* fwHeadModeExt */
152
        bytestream_put_le16(&riff_extradata, 0);
153
        /* wHeadEmphasis */
154
        bytestream_put_le16(&riff_extradata, 1);
155
        /* fwHeadFlags */
156
        bytestream_put_le16(&riff_extradata, 16);
157
        /* dwPTSLow */
158
        bytestream_put_le32(&riff_extradata, 0);
159
        /* dwPTSHigh */
160
        bytestream_put_le32(&riff_extradata, 0);
161
    } else if (enc->codec_id == AV_CODEC_ID_G723_1) {
162
        hdrsize += 20;
163
        bytestream_put_le32(&riff_extradata, 0x9ace0002); /* extradata needed for msacm g723.1 codec */
164
        bytestream_put_le32(&riff_extradata, 0xaea2f732);
165
        bytestream_put_le16(&riff_extradata, 0xacde);
166
    } else if (enc->codec_id == AV_CODEC_ID_GSM_MS ||
167
               enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
168
        hdrsize += 2;
169
        /* wSamplesPerBlock */
170
        bytestream_put_le16(&riff_extradata, frame_size);
171
    } else if (enc->extradata_size) {
172
        riff_extradata_start = enc->extradata;
173
        riff_extradata       = enc->extradata + enc->extradata_size;
174
        hdrsize             += enc->extradata_size;
175
    }
176
    /* write WAVEFORMATEXTENSIBLE extensions */
177
    if (waveformatextensible) {
178
        hdrsize += 22;
179
        /* 22 is WAVEFORMATEXTENSIBLE size */
180
        avio_wl16(pb, riff_extradata - riff_extradata_start + 22);
181
        /* ValidBitsPerSample || SamplesPerBlock || Reserved */
182
        avio_wl16(pb, bps);
183
        /* dwChannelMask */
184
        avio_wl32(pb, enc->channel_layout);
185
        /* GUID + next 3 */
186
        avio_wl32(pb, enc->codec_tag);
187
        avio_wl32(pb, 0x00100000);
188
        avio_wl32(pb, 0xAA000080);
189
        avio_wl32(pb, 0x719B3800);
190
    } else {
191
        avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */
192
    }
193
    avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start);
194
    if (hdrsize & 1) {
195
        hdrsize++;
196
        avio_w8(pb, 0);
197
    }
198
 
199
    return hdrsize;
200
}
201
 
202
/* BITMAPINFOHEADER header */
203
void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc,
204
                       const AVCodecTag *tags, int for_asf)
205
{
206
    /* size */
207
    avio_wl32(pb, 40 + enc->extradata_size);
208
    avio_wl32(pb, enc->width);
209
    //We always store RGB TopDown
210
    avio_wl32(pb, enc->codec_tag ? enc->height : -enc->height);
211
    /* planes */
212
    avio_wl16(pb, 1);
213
    /* depth */
214
    avio_wl16(pb, enc->bits_per_coded_sample ? enc->bits_per_coded_sample : 24);
215
    /* compression type */
216
    avio_wl32(pb, enc->codec_tag);
217
    avio_wl32(pb, (enc->width * enc->height * (enc->bits_per_coded_sample ? enc->bits_per_coded_sample : 24)+7) / 8);
218
    avio_wl32(pb, 0);
219
    avio_wl32(pb, 0);
220
    avio_wl32(pb, 0);
221
    avio_wl32(pb, 0);
222
 
223
    avio_write(pb, enc->extradata, enc->extradata_size);
224
 
225
    if (!for_asf && enc->extradata_size & 1)
226
        avio_w8(pb, 0);
227
}
228
 
229
void ff_parse_specific_params(AVCodecContext *stream, int *au_rate,
230
                              int *au_ssize, int *au_scale)
231
{
232
    int gcd;
233
    int audio_frame_size;
234
 
235
    /* We use the known constant frame size for the codec if known, otherwise
236
     * fall back on using AVCodecContext.frame_size, which is not as reliable
237
     * for indicating packet duration. */
238
    audio_frame_size = av_get_audio_frame_duration(stream, 0);
239
    if (!audio_frame_size)
240
        audio_frame_size = stream->frame_size;
241
 
242
    *au_ssize = stream->block_align;
243
    if (audio_frame_size && stream->sample_rate) {
244
        *au_scale = audio_frame_size;
245
        *au_rate  = stream->sample_rate;
246
    } else if (stream->codec_type == AVMEDIA_TYPE_VIDEO ||
247
               stream->codec_type == AVMEDIA_TYPE_DATA ||
248
               stream->codec_type == AVMEDIA_TYPE_SUBTITLE) {
249
        *au_scale = stream->time_base.num;
250
        *au_rate  = stream->time_base.den;
251
    } else {
252
        *au_scale = stream->block_align ? stream->block_align * 8 : 8;
253
        *au_rate  = stream->bit_rate ? stream->bit_rate :
254
                    8 * stream->sample_rate;
255
    }
256
    gcd        = av_gcd(*au_scale, *au_rate);
257
    *au_scale /= gcd;
258
    *au_rate  /= gcd;
259
}
260
 
261
void ff_riff_write_info_tag(AVIOContext *pb, const char *tag, const char *str)
262
{
263
    int len = strlen(str);
264
    if (len > 0) {
265
        len++;
266
        ffio_wfourcc(pb, tag);
267
        avio_wl32(pb, len);
268
        avio_put_str(pb, str);
269
        if (len & 1)
270
            avio_w8(pb, 0);
271
    }
272
}
273
 
274
static const char riff_tags[][5] = {
275
    "IARL", "IART", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI",
276
    "IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD",
277
    "IPRT", "ITRK", "ISBJ", "ISFT", "ISHP", "ISMP", "ISRC", "ISRF", "ITCH",
278
    { 0 }
279
};
280
 
281
static int riff_has_valid_tags(AVFormatContext *s)
282
{
283
    int i;
284
 
285
    for (i = 0; *riff_tags[i]; i++)
286
        if (av_dict_get(s->metadata, riff_tags[i], NULL, AV_DICT_MATCH_CASE))
287
            return 1;
288
 
289
    return 0;
290
}
291
 
292
void ff_riff_write_info(AVFormatContext *s)
293
{
294
    AVIOContext *pb = s->pb;
295
    int i;
296
    int64_t list_pos;
297
    AVDictionaryEntry *t = NULL;
298
 
299
    ff_metadata_conv(&s->metadata, ff_riff_info_conv, NULL);
300
 
301
    /* writing empty LIST is not nice and may cause problems */
302
    if (!riff_has_valid_tags(s))
303
        return;
304
 
305
    list_pos = ff_start_tag(pb, "LIST");
306
    ffio_wfourcc(pb, "INFO");
307
    for (i = 0; *riff_tags[i]; i++)
308
        if ((t = av_dict_get(s->metadata, riff_tags[i],
309
                             NULL, AV_DICT_MATCH_CASE)))
310
            ff_riff_write_info_tag(s->pb, t->key, t->value);
311
    ff_end_tag(pb, list_pos);
312
}