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

« back to all changes in this revision

Viewing changes to ffmpeg/libavformat/ogg.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:
4
4
 *
5
5
 * Uses libogg, but requires libvorbisenc to construct correct headers
6
6
 * when containing Vorbis stream -- currently the only format supported
 
7
 *
 
8
 * This file is part of FFmpeg.
 
9
 *
 
10
 * FFmpeg is free software; you can redistribute it and/or
 
11
 * modify it under the terms of the GNU Lesser General Public
 
12
 * License as published by the Free Software Foundation; either
 
13
 * version 2.1 of the License, or (at your option) any later version.
 
14
 *
 
15
 * FFmpeg is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
 * Lesser General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU Lesser General Public
 
21
 * License along with FFmpeg; if not, write to the Free Software
 
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
7
23
 */
8
24
 
9
25
#include <stdio.h>
10
 
#include <time.h>
11
26
 
12
27
#include <ogg/ogg.h>
13
 
#include <vorbis/vorbisenc.h>
14
28
 
15
29
#include "avformat.h"
16
 
#include "oggvorbis.h"
 
30
 
 
31
#undef NDEBUG
 
32
#include <assert.h>
17
33
 
18
34
#define DECODER_BUFFER_SIZE 4096
19
35
 
22
38
    /* output */
23
39
    ogg_stream_state os ;
24
40
    int header_handled ;
25
 
    ogg_int64_t base_packet_no ;
26
 
    ogg_int64_t base_granule_pos ;
 
41
    ogg_packet op;
27
42
 
28
43
    /* input */
29
44
    ogg_sync_state oy ;
30
45
} OggContext ;
31
46
 
32
47
 
33
 
static int ogg_write_header(AVFormatContext *avfcontext) 
 
48
#ifdef CONFIG_MUXERS
 
49
static int ogg_write_header(AVFormatContext *avfcontext)
34
50
{
35
51
    OggContext *context = avfcontext->priv_data;
36
 
    AVCodecContext *avccontext ;
37
 
    vorbis_info vi ;
38
 
    vorbis_dsp_state vd ;
39
 
    vorbis_comment vc ;
40
 
    vorbis_block vb ;
41
 
    ogg_packet header, header_comm, header_code ; 
42
 
    int n ;
43
 
    
44
 
    srand(time(NULL));
45
 
    ogg_stream_init(&context->os, rand());
46
 
    
 
52
    ogg_packet *op= &context->op;
 
53
    int n;
 
54
 
 
55
    ogg_stream_init(&context->os, 31415);
 
56
 
47
57
    for(n = 0 ; n < avfcontext->nb_streams ; n++) {
48
 
        avccontext = &avfcontext->streams[n]->codec ;
49
 
 
50
 
        /* begin vorbis specific code */
51
 
                
52
 
        vorbis_info_init(&vi) ;
53
 
 
54
 
        /* code copied from libavcodec/oggvorbis.c */
55
 
 
56
 
        if(oggvorbis_init_encoder(&vi, avccontext) < 0) {
57
 
            fprintf(stderr, "ogg_write_header: init_encoder failed") ;
58
 
            return -1 ;
59
 
        }
60
 
 
61
 
        vorbis_analysis_init(&vd, &vi) ;
62
 
        vorbis_block_init(&vd, &vb) ;
63
 
        
64
 
        vorbis_comment_init(&vc) ;
65
 
        vorbis_comment_add_tag(&vc, "encoder", "ffmpeg") ;
66
 
        if(*avfcontext->title)
67
 
            vorbis_comment_add_tag(&vc, "title", avfcontext->title) ;
68
 
 
69
 
        vorbis_analysis_headerout(&vd, &vc, &header,
70
 
                                  &header_comm, &header_code) ;
71
 
        ogg_stream_packetin(&context->os, &header) ;
72
 
        ogg_stream_packetin(&context->os, &header_comm) ;
73
 
        ogg_stream_packetin(&context->os, &header_code) ;  
74
 
        
75
 
        vorbis_block_clear(&vb) ;
76
 
        vorbis_dsp_clear(&vd) ;
77
 
        vorbis_info_clear(&vi) ;
78
 
        vorbis_comment_clear(&vc) ;
79
 
        
80
 
        /* end of vorbis specific code */
81
 
 
82
 
        context->header_handled = 0 ;
83
 
        context->base_packet_no = 0 ;
 
58
        AVCodecContext *codec = avfcontext->streams[n]->codec;
 
59
        uint8_t *headers = codec->extradata;
 
60
        int headers_len = codec->extradata_size;
 
61
        uint8_t *header_start[3];
 
62
        int header_len[3];
 
63
        int i, j;
 
64
 
 
65
        av_set_pts_info(avfcontext->streams[n], 60, 1, AV_TIME_BASE);
 
66
 
 
67
        for(j=1,i=0;i<2;++i, ++j) {
 
68
            header_len[i]=0;
 
69
            while(j<headers_len && headers[j]==0xff) {
 
70
                header_len[i]+=0xff;
 
71
                ++j;
 
72
            }
 
73
            header_len[i]+=headers[j];
 
74
        }
 
75
        header_len[2]=headers_len-header_len[0]-header_len[1]-j;
 
76
        headers+=j;
 
77
        header_start[0] = headers;
 
78
        header_start[1] = header_start[0] + header_len[0];
 
79
        header_start[2] = header_start[1] + header_len[1];
 
80
 
 
81
        for(i=0; i < 3; ++i){
 
82
            op->bytes = header_len[i];
 
83
 
 
84
            op->packet= header_start[i];
 
85
            op->b_o_s= op->packetno==0;
 
86
 
 
87
            ogg_stream_packetin(&context->os, op);
 
88
 
 
89
            op->packetno++; //FIXME multiple streams
 
90
        }
 
91
 
 
92
        context->header_handled = 0 ;
84
93
    }
85
 
    
 
94
 
86
95
    return 0 ;
87
96
}
88
97
 
89
 
 
90
 
static int ogg_write_packet(AVFormatContext *avfcontext,
91
 
                            int stream_index,
92
 
                            unsigned char *buf, int size, int force_pts)
 
98
static int ogg_write_packet(AVFormatContext *avfcontext, AVPacket *pkt)
93
99
{
94
100
    OggContext *context = avfcontext->priv_data ;
95
 
    ogg_packet *op ;
 
101
    AVCodecContext *avctx= avfcontext->streams[pkt->stream_index]->codec;
 
102
    ogg_packet *op= &context->op;
96
103
    ogg_page og ;
97
 
    int l = 0 ;
98
 
    
 
104
    int64_t pts;
 
105
 
 
106
    pts= av_rescale(pkt->pts, avctx->sample_rate, AV_TIME_BASE);
 
107
 
 
108
//    av_log(avfcontext, AV_LOG_DEBUG, "M%d\n", size);
 
109
 
99
110
    /* flush header packets so audio starts on a new page */
100
111
 
101
112
    if(!context->header_handled) {
102
 
        while(ogg_stream_flush(&context->os, &og)) {
103
 
            put_buffer(&avfcontext->pb, og.header, og.header_len) ;
104
 
            put_buffer(&avfcontext->pb, og.body, og.body_len) ;
105
 
            put_flush_packet(&avfcontext->pb);
106
 
        }
107
 
        context->header_handled = 1 ;
108
 
    }
109
 
 
110
 
    while(l < size) {
111
 
        op = (ogg_packet*)(buf + l) ;
112
 
        op->packet = buf + l + sizeof(ogg_packet) ; /* fix data pointer */
113
 
 
114
 
        if(!context->base_packet_no) { /* this is the first packet */
115
 
            context->base_packet_no = op->packetno ; 
116
 
            context->base_granule_pos = op->granulepos ;
117
 
        }
118
 
 
119
 
        /* correct the fields in the packet -- essential for streaming */
120
 
 
121
 
        op->packetno -= context->base_packet_no ;
122
 
        op->granulepos -= context->base_granule_pos ;
123
 
 
124
 
        ogg_stream_packetin(&context->os, op) ;
125
 
        l += sizeof(ogg_packet) + op->bytes ;
126
 
 
127
 
        while(ogg_stream_pageout(&context->os, &og)) {
128
 
            put_buffer(&avfcontext->pb, og.header, og.header_len) ;
129
 
            put_buffer(&avfcontext->pb, og.body, og.body_len) ;
130
 
            put_flush_packet(&avfcontext->pb);
131
 
        }
132
 
    }
 
113
        while(ogg_stream_flush(&context->os, &og)) {
 
114
            put_buffer(&avfcontext->pb, og.header, og.header_len) ;
 
115
            put_buffer(&avfcontext->pb, og.body, og.body_len) ;
 
116
            put_flush_packet(&avfcontext->pb);
 
117
        }
 
118
        context->header_handled = 1 ;
 
119
    }
 
120
 
 
121
    op->packet = (uint8_t*) pkt->data;
 
122
    op->bytes  = pkt->size;
 
123
    op->b_o_s  = op->packetno == 0;
 
124
    op->granulepos= pts;
 
125
 
 
126
    /* correct the fields in the packet -- essential for streaming */
 
127
 
 
128
    ogg_stream_packetin(&context->os, op);
 
129
 
 
130
    while(ogg_stream_pageout(&context->os, &og)) {
 
131
        put_buffer(&avfcontext->pb, og.header, og.header_len);
 
132
        put_buffer(&avfcontext->pb, og.body, og.body_len);
 
133
        put_flush_packet(&avfcontext->pb);
 
134
    }
 
135
    op->packetno++;
133
136
 
134
137
    return 0;
135
138
}
140
143
    ogg_page og ;
141
144
 
142
145
    while(ogg_stream_flush(&context->os, &og)) {
143
 
        put_buffer(&avfcontext->pb, og.header, og.header_len) ;
144
 
        put_buffer(&avfcontext->pb, og.body, og.body_len) ;
145
 
        put_flush_packet(&avfcontext->pb);
 
146
        put_buffer(&avfcontext->pb, og.header, og.header_len) ;
 
147
        put_buffer(&avfcontext->pb, og.body, og.body_len) ;
 
148
        put_flush_packet(&avfcontext->pb);
146
149
    }
147
150
 
148
151
    ogg_stream_clear(&context->os) ;
150
153
}
151
154
 
152
155
 
153
 
static AVOutputFormat ogg_oformat = {
 
156
AVOutputFormat ogg_muxer = {
154
157
    "ogg",
155
 
    "Ogg Vorbis",
156
 
    "audio/x-vorbis",
 
158
    "Ogg format",
 
159
    "application/ogg",
157
160
    "ogg",
158
161
    sizeof(OggContext),
159
162
    CODEC_ID_VORBIS,
162
165
    ogg_write_packet,
163
166
    ogg_write_trailer,
164
167
} ;
165
 
 
166
 
 
 
168
#endif //CONFIG_MUXERS
 
169
 
 
170
#if 0
167
171
static int next_packet(AVFormatContext *avfcontext, ogg_packet *op) {
168
172
    OggContext *context = avfcontext->priv_data ;
169
173
    ogg_page og ;
171
175
 
172
176
    while(ogg_stream_packetout(&context->os, op) != 1) {
173
177
 
174
 
        /* while no pages are available, read in more data to the sync */
175
 
        while(ogg_sync_pageout(&context->oy, &og) != 1) {
176
 
            buf = ogg_sync_buffer(&context->oy, DECODER_BUFFER_SIZE) ;
177
 
            if(get_buffer(&avfcontext->pb, buf, DECODER_BUFFER_SIZE) <= 0)
178
 
                return 1 ;
179
 
            ogg_sync_wrote(&context->oy, DECODER_BUFFER_SIZE) ; 
180
 
        }       
181
 
        
182
 
        /* got a page. Feed it into the stream and get the packet */
183
 
        if(ogg_stream_pagein(&context->os, &og) != 0)
184
 
            return 1 ;
 
178
        /* while no pages are available, read in more data to the sync */
 
179
        while(ogg_sync_pageout(&context->oy, &og) != 1) {
 
180
            buf = ogg_sync_buffer(&context->oy, DECODER_BUFFER_SIZE) ;
 
181
            if(get_buffer(&avfcontext->pb, buf, DECODER_BUFFER_SIZE) <= 0)
 
182
                return 1 ;
 
183
            ogg_sync_wrote(&context->oy, DECODER_BUFFER_SIZE) ;
 
184
        }
 
185
 
 
186
        /* got a page. Feed it into the stream and get the packet */
 
187
        if(ogg_stream_pagein(&context->os, &og) != 0)
 
188
            return 1 ;
185
189
    }
186
190
 
187
191
    return 0 ;
191
195
static int ogg_read_header(AVFormatContext *avfcontext, AVFormatParameters *ap)
192
196
{
193
197
    OggContext *context = avfcontext->priv_data;
 
198
    ogg_packet op ;
194
199
    char *buf ;
195
200
    ogg_page og ;
196
201
    AVStream *ast ;
197
 
    
 
202
    AVCodecContext *codec;
 
203
    uint8_t *p;
 
204
    int i;
 
205
 
198
206
    ogg_sync_init(&context->oy) ;
199
207
    buf = ogg_sync_buffer(&context->oy, DECODER_BUFFER_SIZE) ;
200
208
 
201
209
    if(get_buffer(&avfcontext->pb, buf, DECODER_BUFFER_SIZE) <= 0)
202
 
        return -EIO ;
203
 
    
204
 
    ogg_sync_wrote(&context->oy, DECODER_BUFFER_SIZE) ;   
 
210
        return AVERROR_IO ;
 
211
 
 
212
    ogg_sync_wrote(&context->oy, DECODER_BUFFER_SIZE) ;
205
213
    ogg_sync_pageout(&context->oy, &og) ;
206
214
    ogg_stream_init(&context->os, ogg_page_serialno(&og)) ;
207
215
    ogg_stream_pagein(&context->os, &og) ;
208
 
  
 
216
 
209
217
    /* currently only one vorbis stream supported */
210
218
 
211
219
    ast = av_new_stream(avfcontext, 0) ;
212
220
    if(!ast)
213
 
        return AVERROR_NOMEM ;
214
 
 
215
 
    ast->codec.codec_type = CODEC_TYPE_AUDIO ;
216
 
    ast->codec.codec_id = CODEC_ID_VORBIS ;
217
 
    
 
221
        return AVERROR_NOMEM ;
 
222
    av_set_pts_info(ast, 60, 1, AV_TIME_BASE);
 
223
 
 
224
    codec= &ast->codec;
 
225
    codec->codec_type = CODEC_TYPE_AUDIO;
 
226
    codec->codec_id = CODEC_ID_VORBIS;
 
227
    for(i=0; i<3; i++){
 
228
        if(next_packet(avfcontext, &op)){
 
229
            return -1;
 
230
        }
 
231
        if(op.bytes >= (1<<16) || op.bytes < 0)
 
232
            return -1;
 
233
        codec->extradata_size+= 2 + op.bytes;
 
234
        codec->extradata= av_realloc(codec->extradata, codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
 
235
        memset(codec->extradata + codec->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
 
236
        p= codec->extradata + codec->extradata_size - 2 - op.bytes;
 
237
        *(p++)= op.bytes>>8;
 
238
        *(p++)= op.bytes&0xFF;
 
239
        memcpy(p, op.packet, op.bytes);
 
240
    }
 
241
 
218
242
    return 0 ;
219
243
}
220
244
 
222
246
static int ogg_read_packet(AVFormatContext *avfcontext, AVPacket *pkt) {
223
247
    ogg_packet op ;
224
248
 
225
 
    if(next_packet(avfcontext, &op)) 
226
 
        return -EIO ;
227
 
    if(av_new_packet(pkt, sizeof(ogg_packet) + op.bytes) < 0)
228
 
        return -EIO ;
 
249
    if(next_packet(avfcontext, &op))
 
250
        return AVERROR_IO ;
 
251
    if(av_new_packet(pkt, op.bytes) < 0)
 
252
        return AVERROR_IO ;
229
253
    pkt->stream_index = 0 ;
230
 
    memcpy(pkt->data, &op, sizeof(ogg_packet)) ;
231
 
    memcpy(pkt->data + sizeof(ogg_packet), op.packet, op.bytes) ;
 
254
    memcpy(pkt->data, op.packet, op.bytes);
 
255
    if(avfcontext->streams[0]->codec.sample_rate && op.granulepos!=-1)
 
256
        pkt->pts= av_rescale(op.granulepos, AV_TIME_BASE, avfcontext->streams[0]->codec.sample_rate);
 
257
//    printf("%"PRId64" %d %d\n", pkt->pts, (int)op.granulepos, avfcontext->streams[0]->codec.sample_rate);
232
258
 
233
 
    return sizeof(ogg_packet) + op.bytes ;
 
259
    return op.bytes;
234
260
}
235
261
 
236
262
 
254
280
    ogg_read_close,
255
281
    .extensions = "ogg",
256
282
} ;
257
 
 
258
 
 
259
 
int ogg_init(void) {
260
 
    av_register_output_format(&ogg_oformat) ;
261
 
    av_register_input_format(&ogg_iformat);
262
 
    return 0 ;
263
 
}
 
283
#endif