Mercurial > libavformat.hg
annotate oggenc.c @ 6260:5c17c20dd67a libavformat
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
when page buffer is bigger than default buffer size. Max page is 65k.
author | bcoudurier |
---|---|
date | Wed, 14 Jul 2010 23:21:18 +0000 |
parents | a198eb01f895 |
children | f4f55ad4a603 |
rev | line source |
---|---|
2731 | 1 /* |
2 * Ogg muxer | |
3 * Copyright (c) 2007 Baptiste Coudurier <baptiste dot coudurier at free dot fr> | |
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 | |
3286 | 22 #include "libavutil/crc.h" |
6054
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
23 #include "libavutil/random_seed.h" |
3286 | 24 #include "libavcodec/xiph.h" |
25 #include "libavcodec/bytestream.h" | |
4578 | 26 #include "libavcodec/flac.h" |
2731 | 27 #include "avformat.h" |
4418
d5119d75439d
Move declaration of ff_interleave_add_packet to internal.h.
bcoudurier
parents:
4311
diff
changeset
|
28 #include "internal.h" |
5858
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
29 #include "vorbiscomment.h" |
2731 | 30 |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
31 #define MAX_PAGE_SIZE 65025 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
32 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
33 typedef struct { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
34 int64_t granule; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
35 int stream_index; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
36 uint8_t flags; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
37 uint8_t segments_count; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
38 uint8_t segments[255]; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
39 uint8_t data[MAX_PAGE_SIZE]; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
40 uint16_t size; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
41 } OGGPage; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
42 |
2731 | 43 typedef struct { |
44 unsigned page_counter; | |
45 uint8_t *header[3]; | |
46 int header_len[3]; | |
47 /** for theora granule */ | |
48 int kfgshift; | |
49 int64_t last_kf_pts; | |
50 int vrev; | |
3021 | 51 int eos; |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
52 unsigned page_count; ///< number of page buffered |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
53 OGGPage page; ///< current page |
6054
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
54 unsigned serial_num; ///< serial number |
2731 | 55 } OGGStreamContext; |
56 | |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
57 typedef struct OGGPageList { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
58 OGGPage page; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
59 struct OGGPageList *next; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
60 } OGGPageList; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
61 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
62 typedef struct { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
63 OGGPageList *page_list; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
64 } OGGContext; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
65 |
6260
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
66 static void ogg_update_checksum(AVFormatContext *s, ByteIOContext *pb, int64_t crc_offset) |
2731 | 67 { |
6260
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
68 int64_t pos = url_ftell(pb); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
69 uint32_t checksum = get_checksum(pb); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
70 url_fseek(pb, crc_offset, SEEK_SET); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
71 put_be32(pb, checksum); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
72 url_fseek(pb, pos, SEEK_SET); |
2731 | 73 } |
74 | |
6260
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
75 static int ogg_write_page(AVFormatContext *s, OGGPage *page, int extra_flags) |
2731 | 76 { |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
77 OGGStreamContext *oggstream = s->streams[page->stream_index]->priv_data; |
6260
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
78 ByteIOContext *pb; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3593
diff
changeset
|
79 int64_t crc_offset; |
6260
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
80 int ret, size; |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
81 uint8_t *buf; |
2731 | 82 |
6260
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
83 ret = url_open_dyn_buf(&pb); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
84 if (ret < 0) |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
85 return ret; |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
86 init_checksum(pb, ff_crc04C11DB7_update, 0); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
87 put_tag(pb, "OggS"); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
88 put_byte(pb, 0); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
89 put_byte(pb, page->flags | extra_flags); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
90 put_le64(pb, page->granule); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
91 put_le32(pb, oggstream->serial_num); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
92 put_le32(pb, oggstream->page_counter++); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
93 crc_offset = url_ftell(pb); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
94 put_le32(pb, 0); // crc |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
95 put_byte(pb, page->segments_count); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
96 put_buffer(pb, page->segments, page->segments_count); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
97 put_buffer(pb, page->data, page->size); |
5851
d88fc4640994
Correctly write last 0 lacing value when packet size is multiple of 255, patch by Greg Maxwell, gmaxwell at gmail dot com
bcoudurier
parents:
5602
diff
changeset
|
98 |
6260
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
99 ogg_update_checksum(s, pb, crc_offset); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
100 put_flush_packet(pb); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
101 |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
102 size = url_close_dyn_buf(pb, &buf); |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
103 if (size < 0) |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
104 return size; |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
105 |
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
106 put_buffer(s->pb, buf, size); |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2731
diff
changeset
|
107 put_flush_packet(s->pb); |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
108 oggstream->page_count--; |
6260
5c17c20dd67a
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
bcoudurier
parents:
6054
diff
changeset
|
109 return 0; |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
110 } |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
111 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
112 static int64_t ogg_granule_to_timestamp(OGGStreamContext *oggstream, OGGPage *page) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
113 { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
114 if (oggstream->kfgshift) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
115 return (page->granule>>oggstream->kfgshift) + |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
116 (page->granule & ((1<<oggstream->kfgshift)-1)); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
117 else |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
118 return page->granule; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
119 } |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
120 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
121 static int ogg_compare_granule(AVFormatContext *s, OGGPage *next, OGGPage *page) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
122 { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
123 AVStream *st2 = s->streams[next->stream_index]; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
124 AVStream *st = s->streams[page->stream_index]; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
125 int64_t next_granule, cur_granule; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
126 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
127 if (next->granule == -1 || page->granule == -1) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
128 return 0; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
129 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
130 next_granule = av_rescale_q(ogg_granule_to_timestamp(st2->priv_data, next), |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
131 st2->time_base, AV_TIME_BASE_Q); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
132 cur_granule = av_rescale_q(ogg_granule_to_timestamp(st->priv_data, page), |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
133 st ->time_base, AV_TIME_BASE_Q); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
134 return next_granule > cur_granule; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
135 } |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
136 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
137 static int ogg_reset_cur_page(OGGStreamContext *oggstream) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
138 { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
139 oggstream->page.granule = -1; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
140 oggstream->page.flags = 0; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
141 oggstream->page.segments_count = 0; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
142 oggstream->page.size = 0; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
143 return 0; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
144 } |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
145 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
146 static int ogg_buffer_page(AVFormatContext *s, OGGStreamContext *oggstream) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
147 { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
148 OGGContext *ogg = s->priv_data; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
149 OGGPageList **p = &ogg->page_list; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
150 OGGPageList *l = av_mallocz(sizeof(*l)); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
151 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
152 if (!l) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
153 return AVERROR(ENOMEM); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
154 l->page = oggstream->page; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
155 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
156 oggstream->page_count++; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
157 ogg_reset_cur_page(oggstream); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
158 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
159 while (*p) { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
160 if (ogg_compare_granule(s, &(*p)->page, &l->page)) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
161 break; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
162 p = &(*p)->next; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
163 } |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
164 l->next = *p; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
165 *p = l; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
166 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
167 return 0; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
168 } |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
169 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
170 static int ogg_buffer_data(AVFormatContext *s, AVStream *st, |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
171 uint8_t *data, unsigned size, int64_t granule) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
172 { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
173 OGGStreamContext *oggstream = st->priv_data; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
174 int total_segments = size / 255 + 1; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
175 uint8_t *p = data; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
176 int i, segments, len; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
177 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
178 for (i = 0; i < total_segments; ) { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
179 OGGPage *page = &oggstream->page; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
180 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
181 segments = FFMIN(total_segments - i, 255 - page->segments_count); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
182 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
183 if (i && !page->segments_count) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
184 page->flags |= 1; // continued packet |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
185 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
186 memset(page->segments+page->segments_count, 255, segments - 1); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
187 page->segments_count += segments - 1; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
188 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
189 len = FFMIN(size, segments*255); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
190 page->segments[page->segments_count++] = len - (segments-1)*255; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
191 memcpy(page->data+page->size, p, len); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
192 p += len; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
193 size -= len; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
194 i += segments; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
195 page->size += len; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
196 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
197 if (i == total_segments) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
198 page->granule = granule; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
199 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
200 if (page->segments_count == 255) { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
201 ogg_buffer_page(s, oggstream); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
202 } |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
203 } |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
204 return 0; |
2731 | 205 } |
206 | |
5280 | 207 static uint8_t *ogg_write_vorbiscomment(int offset, int bitexact, |
5858
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
208 int *header_len, AVMetadata *m) |
5280 | 209 { |
210 const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT; | |
211 int size; | |
212 uint8_t *p, *p0; | |
5858
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
213 unsigned int count; |
5280 | 214 |
5858
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
215 size = offset + ff_vorbiscomment_length(m, vendor, &count); |
5280 | 216 p = av_mallocz(size); |
217 if (!p) | |
218 return NULL; | |
219 p0 = p; | |
220 | |
221 p += offset; | |
5858
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
222 ff_vorbiscomment_write(&p, m, vendor, count); |
5280 | 223 |
224 *header_len = size; | |
225 return p0; | |
226 } | |
227 | |
4578 | 228 static int ogg_build_flac_headers(AVCodecContext *avctx, |
5858
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
229 OGGStreamContext *oggstream, int bitexact, |
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
230 AVMetadata *m) |
2731 | 231 { |
4578 | 232 enum FLACExtradataFormat format; |
233 uint8_t *streaminfo; | |
2731 | 234 uint8_t *p; |
5054 | 235 |
4578 | 236 if (!ff_flac_is_extradata_valid(avctx, &format, &streaminfo)) |
2731 | 237 return -1; |
5054 | 238 |
239 // first packet: STREAMINFO | |
3188 | 240 oggstream->header_len[0] = 51; |
241 oggstream->header[0] = av_mallocz(51); // per ogg flac specs | |
2731 | 242 p = oggstream->header[0]; |
5053 | 243 if (!p) |
5930
08cd1179a20d
Replace all remaining occurrences of AVERROR_NOMEM with
stefano
parents:
5913
diff
changeset
|
244 return AVERROR(ENOMEM); |
2731 | 245 bytestream_put_byte(&p, 0x7F); |
246 bytestream_put_buffer(&p, "FLAC", 4); | |
247 bytestream_put_byte(&p, 1); // major version | |
248 bytestream_put_byte(&p, 0); // minor version | |
249 bytestream_put_be16(&p, 1); // headers packets without this one | |
250 bytestream_put_buffer(&p, "fLaC", 4); | |
251 bytestream_put_byte(&p, 0x00); // streaminfo | |
252 bytestream_put_be24(&p, 34); | |
4578 | 253 bytestream_put_buffer(&p, streaminfo, FLAC_STREAMINFO_SIZE); |
5054 | 254 |
255 // second packet: VorbisComment | |
5858
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
256 p = ogg_write_vorbiscomment(4, bitexact, &oggstream->header_len[1], m); |
5053 | 257 if (!p) |
5930
08cd1179a20d
Replace all remaining occurrences of AVERROR_NOMEM with
stefano
parents:
5913
diff
changeset
|
258 return AVERROR(ENOMEM); |
5280 | 259 oggstream->header[1] = p; |
2731 | 260 bytestream_put_byte(&p, 0x84); // last metadata block and vorbis comment |
261 bytestream_put_be24(&p, oggstream->header_len[1] - 4); | |
5280 | 262 |
263 return 0; | |
264 } | |
265 | |
266 #define SPEEX_HEADER_SIZE 80 | |
267 | |
268 static int ogg_build_speex_headers(AVCodecContext *avctx, | |
5858
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
269 OGGStreamContext *oggstream, int bitexact, |
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
270 AVMetadata *m) |
5280 | 271 { |
272 uint8_t *p; | |
273 | |
274 if (avctx->extradata_size < SPEEX_HEADER_SIZE) | |
275 return -1; | |
276 | |
277 // first packet: Speex header | |
278 p = av_mallocz(SPEEX_HEADER_SIZE); | |
279 if (!p) | |
5930
08cd1179a20d
Replace all remaining occurrences of AVERROR_NOMEM with
stefano
parents:
5913
diff
changeset
|
280 return AVERROR(ENOMEM); |
5280 | 281 oggstream->header[0] = p; |
282 oggstream->header_len[0] = SPEEX_HEADER_SIZE; | |
283 bytestream_put_buffer(&p, avctx->extradata, SPEEX_HEADER_SIZE); | |
284 AV_WL32(&oggstream->header[0][68], 0); // set extra_headers to 0 | |
285 | |
286 // second packet: VorbisComment | |
5858
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
287 p = ogg_write_vorbiscomment(0, bitexact, &oggstream->header_len[1], m); |
5280 | 288 if (!p) |
5930
08cd1179a20d
Replace all remaining occurrences of AVERROR_NOMEM with
stefano
parents:
5913
diff
changeset
|
289 return AVERROR(ENOMEM); |
5280 | 290 oggstream->header[1] = p; |
5054 | 291 |
2731 | 292 return 0; |
293 } | |
294 | |
295 static int ogg_write_header(AVFormatContext *s) | |
296 { | |
297 OGGStreamContext *oggstream; | |
298 int i, j; | |
6054
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
299 |
2731 | 300 for (i = 0; i < s->nb_streams; i++) { |
301 AVStream *st = s->streams[i]; | |
6054
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
302 unsigned serial_num = i; |
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
303 |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5858
diff
changeset
|
304 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) |
2731 | 305 av_set_pts_info(st, 64, 1, st->codec->sample_rate); |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5858
diff
changeset
|
306 else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) |
2731 | 307 av_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den); |
308 if (st->codec->codec_id != CODEC_ID_VORBIS && | |
309 st->codec->codec_id != CODEC_ID_THEORA && | |
5280 | 310 st->codec->codec_id != CODEC_ID_SPEEX && |
2731 | 311 st->codec->codec_id != CODEC_ID_FLAC) { |
312 av_log(s, AV_LOG_ERROR, "Unsupported codec id in stream %d\n", i); | |
313 return -1; | |
314 } | |
315 | |
316 if (!st->codec->extradata || !st->codec->extradata_size) { | |
317 av_log(s, AV_LOG_ERROR, "No extradata present\n"); | |
318 return -1; | |
319 } | |
320 oggstream = av_mallocz(sizeof(*oggstream)); | |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
321 oggstream->page.stream_index = i; |
6054
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
322 |
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
323 if (!(st->codec->flags & CODEC_FLAG_BITEXACT)) |
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
324 do { |
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
325 serial_num = av_get_random_seed(); |
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
326 for (j = 0; j < i; j++) { |
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
327 OGGStreamContext *sc = s->streams[j]->priv_data; |
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
328 if (serial_num == sc->serial_num) |
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
329 break; |
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
330 } |
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
331 } while (j < i); |
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
332 oggstream->serial_num = serial_num; |
a198eb01f895
In ogg muxer, use random serial number of each ogg streams
bcoudurier
parents:
6028
diff
changeset
|
333 |
2731 | 334 st->priv_data = oggstream; |
335 if (st->codec->codec_id == CODEC_ID_FLAC) { | |
5055
5a6bbdd352fb
oggenc: return error value from ogg_build_flac_headers()
jbr
parents:
5054
diff
changeset
|
336 int err = ogg_build_flac_headers(st->codec, oggstream, |
5858
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
337 st->codec->flags & CODEC_FLAG_BITEXACT, |
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
338 s->metadata); |
5055
5a6bbdd352fb
oggenc: return error value from ogg_build_flac_headers()
jbr
parents:
5054
diff
changeset
|
339 if (err) { |
5056
f67fad61077e
oggenc: Change error log text. An error here does not necessarily mean
jbr
parents:
5055
diff
changeset
|
340 av_log(s, AV_LOG_ERROR, "Error writing FLAC headers\n"); |
2731 | 341 av_freep(&st->priv_data); |
5055
5a6bbdd352fb
oggenc: return error value from ogg_build_flac_headers()
jbr
parents:
5054
diff
changeset
|
342 return err; |
2731 | 343 } |
5280 | 344 } else if (st->codec->codec_id == CODEC_ID_SPEEX) { |
345 int err = ogg_build_speex_headers(st->codec, oggstream, | |
5858
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
346 st->codec->flags & CODEC_FLAG_BITEXACT, |
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
347 s->metadata); |
5280 | 348 if (err) { |
349 av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n"); | |
350 av_freep(&st->priv_data); | |
351 return err; | |
352 } | |
2731 | 353 } else { |
354 if (ff_split_xiph_headers(st->codec->extradata, st->codec->extradata_size, | |
355 st->codec->codec_id == CODEC_ID_VORBIS ? 30 : 42, | |
356 oggstream->header, oggstream->header_len) < 0) { | |
357 av_log(s, AV_LOG_ERROR, "Extradata corrupted\n"); | |
358 av_freep(&st->priv_data); | |
359 return -1; | |
360 } | |
361 if (st->codec->codec_id == CODEC_ID_THEORA) { | |
362 /** KFGSHIFT is the width of the less significant section of the granule position | |
363 The less significant section is the frame count since the last keyframe */ | |
364 oggstream->kfgshift = ((oggstream->header[0][40]&3)<<3)|(oggstream->header[0][41]>>5); | |
365 oggstream->vrev = oggstream->header[0][9]; | |
366 av_log(s, AV_LOG_DEBUG, "theora kfgshift %d, vrev %d\n", | |
367 oggstream->kfgshift, oggstream->vrev); | |
368 } | |
369 } | |
370 } | |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
371 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
372 for (j = 0; j < s->nb_streams; j++) { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
373 OGGStreamContext *oggstream = s->streams[j]->priv_data; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
374 ogg_buffer_data(s, s->streams[j], oggstream->header[0], |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
375 oggstream->header_len[0], 0); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
376 oggstream->page.flags |= 2; // bos |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
377 ogg_buffer_page(s, oggstream); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
378 } |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
379 for (j = 0; j < s->nb_streams; j++) { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
380 AVStream *st = s->streams[j]; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
381 OGGStreamContext *oggstream = st->priv_data; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
382 for (i = 1; i < 3; i++) { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
383 if (oggstream && oggstream->header_len[i]) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
384 ogg_buffer_data(s, st, oggstream->header[i], |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
385 oggstream->header_len[i], 0); |
2731 | 386 } |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
387 ogg_buffer_page(s, oggstream); |
2731 | 388 } |
389 return 0; | |
390 } | |
391 | |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
392 static void ogg_write_pages(AVFormatContext *s, int flush) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
393 { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
394 OGGContext *ogg = s->priv_data; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
395 OGGPageList *next, *p; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
396 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
397 if (!ogg->page_list) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
398 return; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
399 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
400 for (p = ogg->page_list; p; ) { |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
401 OGGStreamContext *oggstream = |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
402 s->streams[p->page.stream_index]->priv_data; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
403 if (oggstream->page_count < 2 && !flush) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
404 break; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
405 ogg_write_page(s, &p->page, |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
406 flush && oggstream->page_count == 1 ? 4 : 0); // eos |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
407 next = p->next; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
408 av_freep(&p); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
409 p = next; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
410 } |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
411 ogg->page_list = p; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
412 } |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
413 |
2731 | 414 static int ogg_write_packet(AVFormatContext *s, AVPacket *pkt) |
415 { | |
416 AVStream *st = s->streams[pkt->stream_index]; | |
417 OGGStreamContext *oggstream = st->priv_data; | |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
418 int ret; |
2731 | 419 int64_t granule; |
420 | |
421 if (st->codec->codec_id == CODEC_ID_THEORA) { | |
422 int64_t pts = oggstream->vrev < 1 ? pkt->pts : pkt->pts + pkt->duration; | |
423 int pframe_count; | |
5913
11bb10c37225
Replace all occurences of PKT_FLAG_KEY with AV_PKT_FLAG_KEY.
cehoyos
parents:
5910
diff
changeset
|
424 if (pkt->flags & AV_PKT_FLAG_KEY) |
2731 | 425 oggstream->last_kf_pts = pts; |
426 pframe_count = pts - oggstream->last_kf_pts; | |
427 // prevent frame count from overflow if key frame flag is not set | |
428 if (pframe_count >= (1<<oggstream->kfgshift)) { | |
429 oggstream->last_kf_pts += pframe_count; | |
430 pframe_count = 0; | |
431 } | |
432 granule = (oggstream->last_kf_pts<<oggstream->kfgshift) | pframe_count; | |
433 } else | |
434 granule = pkt->pts + pkt->duration; | |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
435 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
436 ret = ogg_buffer_data(s, st, pkt->data, pkt->size, granule); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
437 if (ret < 0) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
438 return ret; |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
439 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
440 ogg_write_pages(s, 0); |
2731 | 441 |
442 return 0; | |
443 } | |
444 | |
445 static int ogg_write_trailer(AVFormatContext *s) | |
446 { | |
447 int i; | |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
448 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
449 /* flush current page */ |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
450 for (i = 0; i < s->nb_streams; i++) |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
451 ogg_buffer_page(s, s->streams[i]->priv_data); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
452 |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
453 ogg_write_pages(s, 1); |
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
454 |
2731 | 455 for (i = 0; i < s->nb_streams; i++) { |
456 AVStream *st = s->streams[i]; | |
457 OGGStreamContext *oggstream = st->priv_data; | |
5280 | 458 if (st->codec->codec_id == CODEC_ID_FLAC || |
459 st->codec->codec_id == CODEC_ID_SPEEX) { | |
2731 | 460 av_free(oggstream->header[0]); |
461 av_free(oggstream->header[1]); | |
462 } | |
463 av_freep(&st->priv_data); | |
464 } | |
465 return 0; | |
466 } | |
467 | |
468 AVOutputFormat ogg_muxer = { | |
469 "ogg", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3286
diff
changeset
|
470 NULL_IF_CONFIG_SMALL("Ogg"), |
2731 | 471 "application/ogg", |
5280 | 472 "ogg,ogv,spx", |
6027
710cc5866cbf
In ogg muxer, pack multiple frames into one page, much lower overhead
bcoudurier
parents:
5930
diff
changeset
|
473 sizeof(OGGContext), |
2731 | 474 CODEC_ID_FLAC, |
475 CODEC_ID_THEORA, | |
476 ogg_write_header, | |
477 ogg_write_packet, | |
478 ogg_write_trailer, | |
5858
274fed269b59
Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
jbr
parents:
5851
diff
changeset
|
479 .metadata_conv = ff_vorbiscomment_metadata_conv, |
2731 | 480 }; |