Mercurial > libavformat.hg
annotate nutenc.c @ 6323:4a52e54b7c12 libavformat
Remove duplicate initialiser for cavsvideo_muxer.extensions
The extensions field was initialised first to "cavs", then to "avs".
The name "cavs" is kept since this is used for the format elsewhere
and "avs" is already used for avisynth files.
author | mru |
---|---|
date | Tue, 27 Jul 2010 08:21:23 +0000 |
parents | 79fc252c65cd |
children | b3aea89a4f63 |
rev | line source |
---|---|
2324 | 1 /* |
2 * nut muxer | |
3 * Copyright (c) 2004-2007 Michael Niedermayer | |
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 | |
4201
7d2f3f1b68d8
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
4076
diff
changeset
|
22 #include "libavutil/intreadwrite.h" |
3286 | 23 #include "libavutil/tree.h" |
24 #include "libavcodec/mpegaudiodata.h" | |
2324 | 25 #include "nut.h" |
6033 | 26 #include "internal.h" |
3046 | 27 |
28 static int find_expected_header(AVCodecContext *c, int size, int key_frame, uint8_t out[64]){ | |
29 int sample_rate= c->sample_rate; | |
30 | |
31 if(size>4096) | |
32 return 0; | |
33 | |
34 AV_WB24(out, 1); | |
35 | |
36 if(c->codec_id == CODEC_ID_MPEG4){ | |
37 if(key_frame){ | |
38 return 3; | |
39 }else{ | |
40 out[3]= 0xB6; | |
41 return 4; | |
42 } | |
43 }else if(c->codec_id == CODEC_ID_MPEG1VIDEO || c->codec_id == CODEC_ID_MPEG2VIDEO){ | |
44 return 3; | |
45 }else if(c->codec_id == CODEC_ID_H264){ | |
46 return 3; | |
47 }else if(c->codec_id == CODEC_ID_MP3 || c->codec_id == CODEC_ID_MP2){ | |
48 int lsf, mpeg25, sample_rate_index, bitrate_index, frame_size; | |
49 int layer= c->codec_id == CODEC_ID_MP3 ? 3 : 2; | |
50 unsigned int header= 0xFFF00000; | |
51 | |
52 lsf = sample_rate < (24000+32000)/2; | |
53 mpeg25 = sample_rate < (12000+16000)/2; | |
54 sample_rate <<= lsf + mpeg25; | |
55 if (sample_rate < (32000 + 44100)/2) sample_rate_index=2; | |
56 else if(sample_rate < (44100 + 48000)/2) sample_rate_index=0; | |
57 else sample_rate_index=1; | |
58 | |
59 sample_rate= ff_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); | |
60 | |
61 for(bitrate_index=2; bitrate_index<30; bitrate_index++){ | |
62 frame_size = ff_mpa_bitrate_tab[lsf][layer-1][bitrate_index>>1]; | |
63 frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index&1); | |
64 | |
65 if(frame_size == size) | |
66 break; | |
67 } | |
68 | |
69 header |= (!lsf)<<19; | |
70 header |= (4-layer)<<17; | |
71 header |= 1<<16; //no crc | |
72 AV_WB32(out, header); | |
73 if(size <= 0) | |
3135 | 74 return 2; //we guess there is no crc, if there is one the user clearly does not care about overhead |
3046 | 75 if(bitrate_index == 30) |
76 return -1; //something is wrong ... | |
77 | |
78 header |= (bitrate_index>>1)<<12; | |
79 header |= sample_rate_index<<10; | |
80 header |= (bitrate_index&1)<<9; | |
81 | |
82 return 2; //FIXME actually put the needed ones in build_elision_headers() | |
3135 | 83 return 3; //we guess that the private bit is not set |
84 //FIXME the above assumptions should be checked, if these turn out false too often something should be done | |
3046 | 85 } |
86 return 0; | |
87 } | |
88 | |
89 static int find_header_idx(AVFormatContext *s, AVCodecContext *c, int size, int frame_type){ | |
90 NUTContext *nut = s->priv_data; | |
91 uint8_t out[64]; | |
92 int i; | |
93 int len= find_expected_header(c, size, frame_type, out); | |
94 | |
95 //av_log(NULL, AV_LOG_ERROR, "expected_h len=%d size=%d codec_id=%d\n", len, size, c->codec_id); | |
96 | |
97 for(i=1; i<nut->header_count; i++){ | |
98 if( len == nut->header_len[i] | |
99 && !memcmp(out, nut->header[i], len)){ | |
100 // av_log(NULL, AV_LOG_ERROR, "found %d\n", i); | |
101 return i; | |
102 } | |
103 } | |
104 // av_log(NULL, AV_LOG_ERROR, "nothing found\n"); | |
105 return 0; | |
106 } | |
107 | |
108 static void build_elision_headers(AVFormatContext *s){ | |
109 NUTContext *nut = s->priv_data; | |
110 int i; | |
111 //FIXME this is lame | |
112 //FIXME write a 2pass mode to find the maximal headers | |
4520
c9ef08e6e4a9
cosmetics: 'const static' --> 'static const' to avoid warnings of the type
diego
parents:
4206
diff
changeset
|
113 static const uint8_t headers[][5]={ |
3046 | 114 {3, 0x00, 0x00, 0x01}, |
115 {4, 0x00, 0x00, 0x01, 0xB6}, | |
116 {2, 0xFF, 0xFA}, //mp3+crc | |
117 {2, 0xFF, 0xFB}, //mp3 | |
118 {2, 0xFF, 0xFC}, //mp2+crc | |
119 {2, 0xFF, 0xFD}, //mp2 | |
120 }; | |
121 | |
122 nut->header_count= 7; | |
123 for(i=1; i<nut->header_count; i++){ | |
124 nut->header_len[i]= headers[i-1][0]; | |
125 nut->header [i]= &headers[i-1][1]; | |
126 } | |
127 } | |
2324 | 128 |
129 static void build_frame_code(AVFormatContext *s){ | |
130 NUTContext *nut = s->priv_data; | |
131 int key_frame, index, pred, stream_id; | |
132 int start=1; | |
133 int end= 254; | |
134 int keyframe_0_esc= s->nb_streams > 2; | |
135 int pred_table[10]; | |
2339
2c8579bcd287
add a universal fallback frame code for the case that no other applies
michael
parents:
2332
diff
changeset
|
136 FrameCode *ft; |
2c8579bcd287
add a universal fallback frame code for the case that no other applies
michael
parents:
2332
diff
changeset
|
137 |
2c8579bcd287
add a universal fallback frame code for the case that no other applies
michael
parents:
2332
diff
changeset
|
138 ft= &nut->frame_code[start]; |
2c8579bcd287
add a universal fallback frame code for the case that no other applies
michael
parents:
2332
diff
changeset
|
139 ft->flags= FLAG_CODED; |
2c8579bcd287
add a universal fallback frame code for the case that no other applies
michael
parents:
2332
diff
changeset
|
140 ft->size_mul=1; |
2c8579bcd287
add a universal fallback frame code for the case that no other applies
michael
parents:
2332
diff
changeset
|
141 ft->pts_delta=1; |
2c8579bcd287
add a universal fallback frame code for the case that no other applies
michael
parents:
2332
diff
changeset
|
142 start++; |
2324 | 143 |
144 if(keyframe_0_esc){ | |
145 /* keyframe = 0 escape */ | |
146 FrameCode *ft= &nut->frame_code[start]; | |
147 ft->flags= FLAG_STREAM_ID | FLAG_SIZE_MSB | FLAG_CODED_PTS; | |
148 ft->size_mul=1; | |
149 start++; | |
150 } | |
151 | |
152 for(stream_id= 0; stream_id<s->nb_streams; stream_id++){ | |
153 int start2= start + (end-start)*stream_id / s->nb_streams; | |
154 int end2 = start + (end-start)*(stream_id+1) / s->nb_streams; | |
155 AVCodecContext *codec = s->streams[stream_id]->codec; | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5902
diff
changeset
|
156 int is_audio= codec->codec_type == AVMEDIA_TYPE_AUDIO; |
2324 | 157 int intra_only= /*codec->intra_only || */is_audio; |
158 int pred_count; | |
159 | |
160 for(key_frame=0; key_frame<2; key_frame++){ | |
161 if(intra_only && keyframe_0_esc && key_frame==0) | |
162 continue; | |
163 | |
164 { | |
165 FrameCode *ft= &nut->frame_code[start2]; | |
166 ft->flags= FLAG_KEY*key_frame; | |
167 ft->flags|= FLAG_SIZE_MSB | FLAG_CODED_PTS; | |
168 ft->stream_id= stream_id; | |
169 ft->size_mul=1; | |
3046 | 170 if(is_audio) |
171 ft->header_idx= find_header_idx(s, codec, -1, key_frame); | |
2324 | 172 start2++; |
173 } | |
174 } | |
175 | |
176 key_frame= intra_only; | |
177 #if 1 | |
178 if(is_audio){ | |
179 int frame_bytes= codec->frame_size*(int64_t)codec->bit_rate / (8*codec->sample_rate); | |
180 int pts; | |
181 for(pts=0; pts<2; pts++){ | |
182 for(pred=0; pred<2; pred++){ | |
183 FrameCode *ft= &nut->frame_code[start2]; | |
184 ft->flags= FLAG_KEY*key_frame; | |
185 ft->stream_id= stream_id; | |
186 ft->size_mul=frame_bytes + 2; | |
187 ft->size_lsb=frame_bytes + pred; | |
188 ft->pts_delta=pts; | |
3046 | 189 ft->header_idx= find_header_idx(s, codec, frame_bytes + pred, key_frame); |
2324 | 190 start2++; |
191 } | |
192 } | |
193 }else{ | |
194 FrameCode *ft= &nut->frame_code[start2]; | |
195 ft->flags= FLAG_KEY | FLAG_SIZE_MSB; | |
196 ft->stream_id= stream_id; | |
197 ft->size_mul=1; | |
198 ft->pts_delta=1; | |
199 start2++; | |
200 } | |
201 #endif | |
202 | |
203 if(codec->has_b_frames){ | |
204 pred_count=5; | |
205 pred_table[0]=-2; | |
206 pred_table[1]=-1; | |
207 pred_table[2]=1; | |
208 pred_table[3]=3; | |
209 pred_table[4]=4; | |
210 }else if(codec->codec_id == CODEC_ID_VORBIS){ | |
211 pred_count=3; | |
212 pred_table[0]=2; | |
213 pred_table[1]=9; | |
214 pred_table[2]=16; | |
215 }else{ | |
216 pred_count=1; | |
217 pred_table[0]=1; | |
218 } | |
219 | |
220 for(pred=0; pred<pred_count; pred++){ | |
221 int start3= start2 + (end2-start2)*pred / pred_count; | |
222 int end3 = start2 + (end2-start2)*(pred+1) / pred_count; | |
223 | |
224 for(index=start3; index<end3; index++){ | |
225 FrameCode *ft= &nut->frame_code[index]; | |
226 ft->flags= FLAG_KEY*key_frame; | |
227 ft->flags|= FLAG_SIZE_MSB; | |
228 ft->stream_id= stream_id; | |
229 //FIXME use single byte size and pred from last | |
230 ft->size_mul= end3-start3; | |
231 ft->size_lsb= index - start3; | |
232 ft->pts_delta= pred_table[pred]; | |
3046 | 233 if(is_audio) |
234 ft->header_idx= find_header_idx(s, codec, -1, key_frame); | |
2324 | 235 } |
236 } | |
237 } | |
238 memmove(&nut->frame_code['N'+1], &nut->frame_code['N'], sizeof(FrameCode)*(255-'N')); | |
239 nut->frame_code[ 0].flags= | |
240 nut->frame_code[255].flags= | |
241 nut->frame_code['N'].flags= FLAG_INVALID; | |
242 } | |
243 | |
4076 | 244 static void put_tt(NUTContext *nut, StreamContext *nus, ByteIOContext *bc, uint64_t val){ |
2342 | 245 val *= nut->time_base_count; |
246 val += nus->time_base - nut->time_base; | |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
247 ff_put_v(bc, val); |
2342 | 248 } |
249 | |
2324 | 250 /** |
6199 | 251 * Store a string as vb. |
2324 | 252 */ |
253 static void put_str(ByteIOContext *bc, const char *string){ | |
254 int len= strlen(string); | |
255 | |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
256 ff_put_v(bc, len); |
2324 | 257 put_buffer(bc, string, len); |
258 } | |
259 | |
260 static void put_s(ByteIOContext *bc, int64_t val){ | |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
261 ff_put_v(bc, 2*FFABS(val) - (val>0)); |
2324 | 262 } |
263 | |
264 #ifdef TRACE | |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
265 static inline void ff_put_v_trace(ByteIOContext *bc, uint64_t v, char *file, char *func, int line){ |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
266 av_log(NULL, AV_LOG_DEBUG, "ff_put_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line); |
2324 | 267 |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
268 ff_put_v(bc, v); |
2324 | 269 } |
270 | |
271 static inline void put_s_trace(ByteIOContext *bc, int64_t v, char *file, char *func, int line){ | |
2344 | 272 av_log(NULL, AV_LOG_DEBUG, "put_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line); |
2324 | 273 |
274 put_s(bc, v); | |
275 } | |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
276 #define ff_put_v(bc, v) ff_put_v_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__) |
2324 | 277 #define put_s(bc, v) put_s_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__) |
278 #endif | |
279 | |
2340 | 280 //FIXME remove calculate_checksum |
2347 | 281 static void put_packet(NUTContext *nut, ByteIOContext *bc, ByteIOContext *dyn_bc, int calculate_checksum, uint64_t startcode){ |
2331
4d1a56112d92
use a dynamic ByteIOContext instead of using the lavf buffer
michael
parents:
2330
diff
changeset
|
282 uint8_t *dyn_buf=NULL; |
4d1a56112d92
use a dynamic ByteIOContext instead of using the lavf buffer
michael
parents:
2330
diff
changeset
|
283 int dyn_size= url_close_dyn_buf(dyn_bc, &dyn_buf); |
2332 | 284 int forw_ptr= dyn_size + 4*calculate_checksum; |
2324 | 285 |
2332 | 286 if(forw_ptr > 4096) |
2683
153d6efc05b8
rename av_crc04C11DB7_update to ff_crc04C11DB7_update and move it to aviobuf.c so it can be reused by other (de)muxers
bcoudurier
parents:
2393
diff
changeset
|
287 init_checksum(bc, ff_crc04C11DB7_update, 0); |
2347 | 288 put_be64(bc, startcode); |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
289 ff_put_v(bc, forw_ptr); |
2332 | 290 if(forw_ptr > 4096) |
291 put_le32(bc, get_checksum(bc)); | |
292 | |
2324 | 293 if(calculate_checksum) |
2683
153d6efc05b8
rename av_crc04C11DB7_update to ff_crc04C11DB7_update and move it to aviobuf.c so it can be reused by other (de)muxers
bcoudurier
parents:
2393
diff
changeset
|
294 init_checksum(bc, ff_crc04C11DB7_update, 0); |
2331
4d1a56112d92
use a dynamic ByteIOContext instead of using the lavf buffer
michael
parents:
2330
diff
changeset
|
295 put_buffer(bc, dyn_buf, dyn_size); |
2324 | 296 if(calculate_checksum) |
2331
4d1a56112d92
use a dynamic ByteIOContext instead of using the lavf buffer
michael
parents:
2330
diff
changeset
|
297 put_le32(bc, get_checksum(bc)); |
2324 | 298 |
2331
4d1a56112d92
use a dynamic ByteIOContext instead of using the lavf buffer
michael
parents:
2330
diff
changeset
|
299 av_free(dyn_buf); |
2324 | 300 } |
301 | |
2329 | 302 static void write_mainheader(NUTContext *nut, ByteIOContext *bc){ |
3046 | 303 int i, j, tmp_pts, tmp_flags, tmp_stream, tmp_mul, tmp_size, tmp_fields, tmp_head_idx; |
304 int64_t tmp_match; | |
2324 | 305 |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
306 ff_put_v(bc, 3); /* version */ |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
307 ff_put_v(bc, nut->avf->nb_streams); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
308 ff_put_v(bc, nut->max_distance); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
309 ff_put_v(bc, nut->time_base_count); |
2324 | 310 |
311 for(i=0; i<nut->time_base_count; i++){ | |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
312 ff_put_v(bc, nut->time_base[i].num); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
313 ff_put_v(bc, nut->time_base[i].den); |
2324 | 314 } |
315 | |
316 tmp_pts=0; | |
317 tmp_mul=1; | |
318 tmp_stream=0; | |
3046 | 319 tmp_match= 1-(1LL<<62); |
320 tmp_head_idx= 0; | |
2324 | 321 for(i=0; i<256;){ |
322 tmp_fields=0; | |
323 tmp_size=0; | |
324 // tmp_res=0; | |
325 if(tmp_pts != nut->frame_code[i].pts_delta) tmp_fields=1; | |
326 if(tmp_mul != nut->frame_code[i].size_mul ) tmp_fields=2; | |
327 if(tmp_stream != nut->frame_code[i].stream_id) tmp_fields=3; | |
328 if(tmp_size != nut->frame_code[i].size_lsb ) tmp_fields=4; | |
329 // if(tmp_res != nut->frame_code[i].res ) tmp_fields=5; | |
3046 | 330 if(tmp_head_idx!=nut->frame_code[i].header_idx)tmp_fields=8; |
2324 | 331 |
332 tmp_pts = nut->frame_code[i].pts_delta; | |
333 tmp_flags = nut->frame_code[i].flags; | |
334 tmp_stream= nut->frame_code[i].stream_id; | |
335 tmp_mul = nut->frame_code[i].size_mul; | |
336 tmp_size = nut->frame_code[i].size_lsb; | |
337 // tmp_res = nut->frame_code[i].res; | |
3046 | 338 tmp_head_idx= nut->frame_code[i].header_idx; |
2324 | 339 |
340 for(j=0; i<256; j++,i++){ | |
341 if(i == 'N'){ | |
342 j--; | |
343 continue; | |
344 } | |
345 if(nut->frame_code[i].pts_delta != tmp_pts ) break; | |
346 if(nut->frame_code[i].flags != tmp_flags ) break; | |
347 if(nut->frame_code[i].stream_id != tmp_stream) break; | |
348 if(nut->frame_code[i].size_mul != tmp_mul ) break; | |
349 if(nut->frame_code[i].size_lsb != tmp_size+j) break; | |
350 // if(nut->frame_code[i].res != tmp_res ) break; | |
3046 | 351 if(nut->frame_code[i].header_idx!= tmp_head_idx) break; |
2324 | 352 } |
353 if(j != tmp_mul - tmp_size) tmp_fields=6; | |
354 | |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
355 ff_put_v(bc, tmp_flags); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
356 ff_put_v(bc, tmp_fields); |
2324 | 357 if(tmp_fields>0) put_s(bc, tmp_pts); |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
358 if(tmp_fields>1) ff_put_v(bc, tmp_mul); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
359 if(tmp_fields>2) ff_put_v(bc, tmp_stream); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
360 if(tmp_fields>3) ff_put_v(bc, tmp_size); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
361 if(tmp_fields>4) ff_put_v(bc, 0 /*tmp_res*/); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
362 if(tmp_fields>5) ff_put_v(bc, j); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
363 if(tmp_fields>6) ff_put_v(bc, tmp_match); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
364 if(tmp_fields>7) ff_put_v(bc, tmp_head_idx); |
3046 | 365 } |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
366 ff_put_v(bc, nut->header_count-1); |
3046 | 367 for(i=1; i<nut->header_count; i++){ |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
368 ff_put_v(bc, nut->header_len[i]); |
3046 | 369 put_buffer(bc, nut->header[i], nut->header_len[i]); |
2324 | 370 } |
2329 | 371 } |
2324 | 372 |
6072
0475ccdb762d
Make write_streamheader() and write_headers() accept an
stefano
parents:
6038
diff
changeset
|
373 static int write_streamheader(AVFormatContext *avctx, ByteIOContext *bc, AVStream *st, int i){ |
0475ccdb762d
Make write_streamheader() and write_headers() accept an
stefano
parents:
6038
diff
changeset
|
374 NUTContext *nut = avctx->priv_data; |
3759
27537074f2a9
convert every muxer/demuxer to write/read sample_aspect_ratio from/to
aurel
parents:
3623
diff
changeset
|
375 AVCodecContext *codec = st->codec; |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
376 ff_put_v(bc, i); |
2330 | 377 switch(codec->codec_type){ |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
378 case AVMEDIA_TYPE_VIDEO: ff_put_v(bc, 0); break; |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
379 case AVMEDIA_TYPE_AUDIO: ff_put_v(bc, 1); break; |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
380 case AVMEDIA_TYPE_SUBTITLE: ff_put_v(bc, 2); break; |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
381 default : ff_put_v(bc, 3); break; |
2330 | 382 } |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
383 ff_put_v(bc, 4); |
2330 | 384 if (codec->codec_tag){ |
385 put_le32(bc, codec->codec_tag); | |
6075
be118b3b67a8
Make write_streamheader() log a message if there is no codec tag
stefano
parents:
6074
diff
changeset
|
386 } else { |
be118b3b67a8
Make write_streamheader() log a message if there is no codec tag
stefano
parents:
6074
diff
changeset
|
387 av_log(avctx, AV_LOG_ERROR, "No codec tag defined for stream %d\n", i); |
6074
258c2ccc68b5
Make write_streamheader() return a meaningful error code if no codec
stefano
parents:
6073
diff
changeset
|
388 return AVERROR(EINVAL); |
6075
be118b3b67a8
Make write_streamheader() log a message if there is no codec tag
stefano
parents:
6074
diff
changeset
|
389 } |
2330 | 390 |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
391 ff_put_v(bc, nut->stream[i].time_base - nut->time_base); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
392 ff_put_v(bc, nut->stream[i].msb_pts_shift); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
393 ff_put_v(bc, nut->stream[i].max_pts_distance); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
394 ff_put_v(bc, codec->has_b_frames); |
2330 | 395 put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */ |
396 | |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
397 ff_put_v(bc, codec->extradata_size); |
2330 | 398 put_buffer(bc, codec->extradata, codec->extradata_size); |
399 | |
400 switch(codec->codec_type){ | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5902
diff
changeset
|
401 case AVMEDIA_TYPE_AUDIO: |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
402 ff_put_v(bc, codec->sample_rate); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
403 ff_put_v(bc, 1); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
404 ff_put_v(bc, codec->channels); |
2330 | 405 break; |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5902
diff
changeset
|
406 case AVMEDIA_TYPE_VIDEO: |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
407 ff_put_v(bc, codec->width); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
408 ff_put_v(bc, codec->height); |
2363 | 409 |
3759
27537074f2a9
convert every muxer/demuxer to write/read sample_aspect_ratio from/to
aurel
parents:
3623
diff
changeset
|
410 if(st->sample_aspect_ratio.num<=0 || st->sample_aspect_ratio.den<=0){ |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
411 ff_put_v(bc, 0); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
412 ff_put_v(bc, 0); |
2363 | 413 }else{ |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
414 ff_put_v(bc, st->sample_aspect_ratio.num); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
415 ff_put_v(bc, st->sample_aspect_ratio.den); |
2363 | 416 } |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
417 ff_put_v(bc, 0); /* csp type -- unknown */ |
2330 | 418 break; |
419 default: | |
420 break; | |
421 } | |
422 return 0; | |
423 } | |
424 | |
3004 | 425 static int add_info(ByteIOContext *bc, const char *type, const char *value){ |
2358 | 426 put_str(bc, type); |
427 put_s(bc, -1); | |
428 put_str(bc, value); | |
429 return 1; | |
430 } | |
431 | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
432 static int write_globalinfo(NUTContext *nut, ByteIOContext *bc){ |
2358 | 433 AVFormatContext *s= nut->avf; |
5704
6b9c2a6d8fa4
Introduce metadata conversion table for NUT muxer and demuxer.
kostya
parents:
5058
diff
changeset
|
434 AVMetadataTag *t = NULL; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
435 ByteIOContext *dyn_bc; |
2358 | 436 uint8_t *dyn_buf=NULL; |
437 int count=0, dyn_size; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
438 int ret = url_open_dyn_buf(&dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
439 if(ret < 0) |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
440 return ret; |
2358 | 441 |
5704
6b9c2a6d8fa4
Introduce metadata conversion table for NUT muxer and demuxer.
kostya
parents:
5058
diff
changeset
|
442 while ((t = av_metadata_get(s->metadata, "", t, AV_METADATA_IGNORE_SUFFIX))) |
6b9c2a6d8fa4
Introduce metadata conversion table for NUT muxer and demuxer.
kostya
parents:
5058
diff
changeset
|
443 count += add_info(dyn_bc, t->key, t->value); |
2358 | 444 |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
445 ff_put_v(bc, 0); //stream_if_plus1 |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
446 ff_put_v(bc, 0); //chapter_id |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
447 ff_put_v(bc, 0); //timestamp_start |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
448 ff_put_v(bc, 0); //length |
2358 | 449 |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
450 ff_put_v(bc, count); |
2358 | 451 |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
452 dyn_size= url_close_dyn_buf(dyn_bc, &dyn_buf); |
2358 | 453 put_buffer(bc, dyn_buf, dyn_size); |
454 av_free(dyn_buf); | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
455 return 0; |
2358 | 456 } |
457 | |
3120
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
458 static int write_streaminfo(NUTContext *nut, ByteIOContext *bc, int stream_id){ |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
459 AVFormatContext *s= nut->avf; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
460 AVStream* st = s->streams[stream_id]; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
461 ByteIOContext *dyn_bc; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
462 uint8_t *dyn_buf=NULL; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
463 int count=0, dyn_size, i; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
464 int ret = url_open_dyn_buf(&dyn_bc); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
465 if(ret < 0) |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
466 return ret; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
467 |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
468 for (i=0; ff_nut_dispositions[i].flag; ++i) { |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
469 if (st->disposition & ff_nut_dispositions[i].flag) |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
470 count += add_info(dyn_bc, "Disposition", ff_nut_dispositions[i].str); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
471 } |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
472 dyn_size = url_close_dyn_buf(dyn_bc, &dyn_buf); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
473 |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
474 if (count) { |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
475 ff_put_v(bc, stream_id + 1); //stream_id_plus1 |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
476 ff_put_v(bc, 0); //chapter_id |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
477 ff_put_v(bc, 0); //timestamp_start |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
478 ff_put_v(bc, 0); //length |
3120
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
479 |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
480 ff_put_v(bc, count); |
3120
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
481 |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
482 put_buffer(bc, dyn_buf, dyn_size); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
483 } |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
484 |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
485 av_free(dyn_buf); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
486 return count; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
487 } |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
488 |
6072
0475ccdb762d
Make write_streamheader() and write_headers() accept an
stefano
parents:
6038
diff
changeset
|
489 static int write_headers(AVFormatContext *avctx, ByteIOContext *bc){ |
0475ccdb762d
Make write_streamheader() and write_headers() accept an
stefano
parents:
6038
diff
changeset
|
490 NUTContext *nut = avctx->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
491 ByteIOContext *dyn_bc; |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
492 int i, ret; |
2345 | 493 |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
494 ret = url_open_dyn_buf(&dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
495 if(ret < 0) |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
496 return ret; |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
497 write_mainheader(nut, dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
498 put_packet(nut, bc, dyn_bc, 1, MAIN_STARTCODE); |
2345 | 499 |
500 for (i=0; i < nut->avf->nb_streams; i++){ | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
501 ret = url_open_dyn_buf(&dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
502 if(ret < 0) |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
503 return ret; |
6073
b9ddee1ca18c
Make write_header() and write_header() return an error code in case of
stefano
parents:
6072
diff
changeset
|
504 if ((ret = write_streamheader(avctx, dyn_bc, nut->avf->streams[i], i)) < 0) |
b9ddee1ca18c
Make write_header() and write_header() return an error code in case of
stefano
parents:
6072
diff
changeset
|
505 return ret; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
506 put_packet(nut, bc, dyn_bc, 1, STREAM_STARTCODE); |
2345 | 507 } |
2358 | 508 |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
509 ret = url_open_dyn_buf(&dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
510 if(ret < 0) |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
511 return ret; |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
512 write_globalinfo(nut, dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
513 put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE); |
2359 | 514 |
3120
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
515 for (i = 0; i < nut->avf->nb_streams; i++) { |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
516 ret = url_open_dyn_buf(&dyn_bc); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
517 if(ret < 0) |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
518 return ret; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
519 ret = write_streaminfo(nut, dyn_bc, i); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
520 if (ret < 0) |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
521 return ret; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
522 if (ret > 0) |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
523 put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
524 else { |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
525 uint8_t* buf; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
526 url_close_dyn_buf(dyn_bc, &buf); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
527 av_free(buf); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
528 } |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
529 } |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
530 |
2359 | 531 nut->last_syncpoint_pos= INT_MIN; |
532 nut->header_count++; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
533 return 0; |
2345 | 534 } |
535 | |
2329 | 536 static int write_header(AVFormatContext *s){ |
537 NUTContext *nut = s->priv_data; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
538 ByteIOContext *bc = s->pb; |
6073
b9ddee1ca18c
Make write_header() and write_header() return an error code in case of
stefano
parents:
6072
diff
changeset
|
539 int i, j, ret; |
2329 | 540 |
541 nut->avf= s; | |
542 | |
543 nut->stream = av_mallocz(sizeof(StreamContext)*s->nb_streams); | |
544 nut->time_base= av_mallocz(sizeof(AVRational )*s->nb_streams); | |
545 | |
546 for(i=0; i<s->nb_streams; i++){ | |
547 AVStream *st= s->streams[i]; | |
548 int ssize; | |
549 AVRational time_base; | |
550 ff_parse_specific_params(st->codec, &time_base.den, &ssize, &time_base.num); | |
551 | |
552 av_set_pts_info(st, 64, time_base.num, time_base.den); | |
553 | |
554 for(j=0; j<nut->time_base_count; j++){ | |
555 if(!memcmp(&time_base, &nut->time_base[j], sizeof(AVRational))){ | |
556 break; | |
557 } | |
558 } | |
559 nut->time_base[j]= time_base; | |
560 nut->stream[i].time_base= &nut->time_base[j]; | |
561 if(j==nut->time_base_count) | |
562 nut->time_base_count++; | |
563 | |
564 if(av_q2d(time_base) >= 0.001) | |
565 nut->stream[i].msb_pts_shift = 7; | |
566 else | |
567 nut->stream[i].msb_pts_shift = 14; | |
568 nut->stream[i].max_pts_distance= FFMAX(1/av_q2d(time_base), 1); | |
569 } | |
570 | |
3014
66fb9d4dea91
nut->max_distance was not set at all anywhere in the NUT muxer
ods15
parents:
3004
diff
changeset
|
571 nut->max_distance = MAX_DISTANCE; |
3046 | 572 build_elision_headers(s); |
2329 | 573 build_frame_code(s); |
574 assert(nut->frame_code['N'].flags == FLAG_INVALID); | |
575 | |
576 put_buffer(bc, ID_STRING, strlen(ID_STRING)); | |
577 put_byte(bc, 0); | |
578 | |
6073
b9ddee1ca18c
Make write_header() and write_header() return an error code in case of
stefano
parents:
6072
diff
changeset
|
579 if ((ret = write_headers(s, bc)) < 0) |
b9ddee1ca18c
Make write_header() and write_header() return an error code in case of
stefano
parents:
6072
diff
changeset
|
580 return ret; |
2325 | 581 |
2324 | 582 put_flush_packet(bc); |
583 | |
2359 | 584 //FIXME index |
2324 | 585 |
586 return 0; | |
587 } | |
588 | |
2343 | 589 static int get_needed_flags(NUTContext *nut, StreamContext *nus, FrameCode *fc, AVPacket *pkt){ |
590 int flags= 0; | |
591 | |
5913
11bb10c37225
Replace all occurences of PKT_FLAG_KEY with AV_PKT_FLAG_KEY.
cehoyos
parents:
5910
diff
changeset
|
592 if(pkt->flags & AV_PKT_FLAG_KEY ) flags |= FLAG_KEY; |
2343 | 593 if(pkt->stream_index != fc->stream_id ) flags |= FLAG_STREAM_ID; |
594 if(pkt->size / fc->size_mul ) flags |= FLAG_SIZE_MSB; | |
595 if(pkt->pts - nus->last_pts != fc->pts_delta) flags |= FLAG_CODED_PTS; | |
596 if(pkt->size > 2*nut->max_distance ) flags |= FLAG_CHECKSUM; | |
597 if(FFABS(pkt->pts - nus->last_pts) | |
598 > nus->max_pts_distance) flags |= FLAG_CHECKSUM; | |
3046 | 599 if( pkt->size < nut->header_len[fc->header_idx] |
600 || (pkt->size > 4096 && fc->header_idx) | |
601 || memcmp(pkt->data, nut->header[fc->header_idx], nut->header_len[fc->header_idx])) | |
602 flags |= FLAG_HEADER_IDX; | |
2343 | 603 |
2371 | 604 return flags | (fc->flags & FLAG_CODED); |
2343 | 605 } |
606 | |
3046 | 607 static int find_best_header_idx(NUTContext *nut, AVPacket *pkt){ |
608 int i; | |
609 int best_i = 0; | |
610 int best_len= 0; | |
611 | |
612 if(pkt->size > 4096) | |
613 return 0; | |
614 | |
615 for(i=1; i<nut->header_count; i++){ | |
616 if( pkt->size >= nut->header_len[i] | |
617 && nut->header_len[i] > best_len | |
618 && !memcmp(pkt->data, nut->header[i], nut->header_len[i])){ | |
619 best_i= i; | |
620 best_len= nut->header_len[i]; | |
621 } | |
622 } | |
623 return best_i; | |
624 } | |
625 | |
2324 | 626 static int write_packet(AVFormatContext *s, AVPacket *pkt){ |
2343 | 627 NUTContext *nut = s->priv_data; |
628 StreamContext *nus= &nut->stream[pkt->stream_index]; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
629 ByteIOContext *bc = s->pb, *dyn_bc; |
2343 | 630 FrameCode *fc; |
631 int64_t coded_pts; | |
3046 | 632 int best_length, frame_code, flags, needed_flags, i, header_idx, best_header_idx; |
5913
11bb10c37225
Replace all occurences of PKT_FLAG_KEY with AV_PKT_FLAG_KEY.
cehoyos
parents:
5910
diff
changeset
|
633 int key_frame = !!(pkt->flags & AV_PKT_FLAG_KEY); |
2343 | 634 int store_sp=0; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
635 int ret; |
2343 | 636 |
3508 | 637 if(pkt->pts < 0) |
638 return -1; | |
639 | |
2359 | 640 if(1LL<<(20+3*nut->header_count) <= url_ftell(bc)) |
6072
0475ccdb762d
Make write_streamheader() and write_headers() accept an
stefano
parents:
6038
diff
changeset
|
641 write_headers(s, bc); |
2359 | 642 |
3015
db8d14740060
Fix intented algo in syncpoint writing before keyframes in NUT muxer
ods15
parents:
3014
diff
changeset
|
643 if(key_frame && !(nus->last_flags & FLAG_KEY)) |
2343 | 644 store_sp= 1; |
645 | |
646 if(pkt->size + 30/*FIXME check*/ + url_ftell(bc) >= nut->last_syncpoint_pos + nut->max_distance) | |
647 store_sp= 1; | |
648 | |
2393 | 649 //FIXME: Ensure store_sp is 1 in the first place. |
2343 | 650 |
651 if(store_sp){ | |
4076 | 652 Syncpoint *sp, dummy= {.pos= INT64_MAX}; |
2350 | 653 |
2343 | 654 ff_nut_reset_ts(nut, *nus->time_base, pkt->dts); |
2350 | 655 for(i=0; i<s->nb_streams; i++){ |
656 AVStream *st= s->streams[i]; | |
3016
eac2648449a5
back_ptr calculation used wrong timebase when searching for back syncpoint
ods15
parents:
3015
diff
changeset
|
657 int64_t dts_tb = av_rescale_rnd(pkt->dts, |
eac2648449a5
back_ptr calculation used wrong timebase when searching for back syncpoint
ods15
parents:
3015
diff
changeset
|
658 nus->time_base->num * (int64_t)nut->stream[i].time_base->den, |
eac2648449a5
back_ptr calculation used wrong timebase when searching for back syncpoint
ods15
parents:
3015
diff
changeset
|
659 nus->time_base->den * (int64_t)nut->stream[i].time_base->num, |
eac2648449a5
back_ptr calculation used wrong timebase when searching for back syncpoint
ods15
parents:
3015
diff
changeset
|
660 AV_ROUND_DOWN); |
eac2648449a5
back_ptr calculation used wrong timebase when searching for back syncpoint
ods15
parents:
3015
diff
changeset
|
661 int index= av_index_search_timestamp(st, dts_tb, AVSEEK_FLAG_BACKWARD); |
2939 | 662 if(index>=0) dummy.pos= FFMIN(dummy.pos, st->index_entries[index].pos); |
2350 | 663 } |
2939 | 664 if(dummy.pos == INT64_MAX) |
665 dummy.pos= 0; | |
5902 | 666 sp= av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp, |
667 NULL); | |
2343 | 668 |
669 nut->last_syncpoint_pos= url_ftell(bc); | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
670 ret = url_open_dyn_buf(&dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
671 if(ret < 0) |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
672 return ret; |
4076 | 673 put_tt(nut, nus, dyn_bc, pkt->dts); |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
674 ff_put_v(dyn_bc, sp ? (nut->last_syncpoint_pos - sp->pos)>>4 : 0); |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
675 put_packet(nut, bc, dyn_bc, 1, SYNCPOINT_STARTCODE); |
2350 | 676 |
677 ff_nut_add_sp(nut, nut->last_syncpoint_pos, 0/*unused*/, pkt->dts); | |
2343 | 678 } |
679 assert(nus->last_pts != AV_NOPTS_VALUE); | |
680 | |
681 coded_pts = pkt->pts & ((1<<nus->msb_pts_shift)-1); | |
682 if(ff_lsb2full(nus, coded_pts) != pkt->pts) | |
683 coded_pts= pkt->pts + (1<<nus->msb_pts_shift); | |
684 | |
3046 | 685 best_header_idx= find_best_header_idx(nut, pkt); |
686 | |
2343 | 687 best_length=INT_MAX; |
688 frame_code= -1; | |
689 for(i=0; i<256; i++){ | |
690 int length= 0; | |
691 FrameCode *fc= &nut->frame_code[i]; | |
692 int flags= fc->flags; | |
693 | |
694 if(flags & FLAG_INVALID) | |
695 continue; | |
696 needed_flags= get_needed_flags(nut, nus, fc, pkt); | |
697 | |
698 if(flags & FLAG_CODED){ | |
699 length++; | |
2372 | 700 flags = needed_flags; |
2343 | 701 } |
702 | |
703 if((flags & needed_flags) != needed_flags) | |
704 continue; | |
705 | |
706 if((flags ^ needed_flags) & FLAG_KEY) | |
707 continue; | |
708 | |
709 if(flags & FLAG_STREAM_ID) | |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
710 length+= ff_get_v_length(pkt->stream_index); |
2343 | 711 |
712 if(pkt->size % fc->size_mul != fc->size_lsb) | |
713 continue; | |
714 if(flags & FLAG_SIZE_MSB) | |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
715 length += ff_get_v_length(pkt->size / fc->size_mul); |
2343 | 716 |
717 if(flags & FLAG_CHECKSUM) | |
718 length+=4; | |
719 | |
720 if(flags & FLAG_CODED_PTS) | |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
721 length += ff_get_v_length(coded_pts); |
2343 | 722 |
3046 | 723 if( (flags & FLAG_CODED) |
724 && nut->header_len[best_header_idx] > nut->header_len[fc->header_idx]+1){ | |
725 flags |= FLAG_HEADER_IDX; | |
726 } | |
727 | |
728 if(flags & FLAG_HEADER_IDX){ | |
729 length += 1 - nut->header_len[best_header_idx]; | |
730 }else{ | |
731 length -= nut->header_len[fc->header_idx]; | |
732 } | |
733 | |
2343 | 734 length*=4; |
735 length+= !(flags & FLAG_CODED_PTS); | |
736 length+= !(flags & FLAG_CHECKSUM); | |
737 | |
738 if(length < best_length){ | |
739 best_length= length; | |
740 frame_code=i; | |
741 } | |
742 } | |
743 assert(frame_code != -1); | |
744 fc= &nut->frame_code[frame_code]; | |
745 flags= fc->flags; | |
746 needed_flags= get_needed_flags(nut, nus, fc, pkt); | |
3046 | 747 header_idx= fc->header_idx; |
2343 | 748 |
2683
153d6efc05b8
rename av_crc04C11DB7_update to ff_crc04C11DB7_update and move it to aviobuf.c so it can be reused by other (de)muxers
bcoudurier
parents:
2393
diff
changeset
|
749 init_checksum(bc, ff_crc04C11DB7_update, 0); |
2343 | 750 put_byte(bc, frame_code); |
751 if(flags & FLAG_CODED){ | |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
752 ff_put_v(bc, (flags^needed_flags) & ~(FLAG_CODED)); |
2343 | 753 flags = needed_flags; |
754 } | |
6245
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
755 if(flags & FLAG_STREAM_ID) ff_put_v(bc, pkt->stream_index); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
756 if(flags & FLAG_CODED_PTS) ff_put_v(bc, coded_pts); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
757 if(flags & FLAG_SIZE_MSB) ff_put_v(bc, pkt->size / fc->size_mul); |
ef4606cc4fb3
rename get_length to ff_get_v_length and put_v to ff_put_v
janne
parents:
6199
diff
changeset
|
758 if(flags & FLAG_HEADER_IDX) ff_put_v(bc, header_idx= best_header_idx); |
2343 | 759 |
760 if(flags & FLAG_CHECKSUM) put_le32(bc, get_checksum(bc)); | |
761 else get_checksum(bc); | |
762 | |
3046 | 763 put_buffer(bc, pkt->data + nut->header_len[header_idx], pkt->size - nut->header_len[header_idx]); |
2343 | 764 nus->last_flags= flags; |
3047 | 765 nus->last_pts= pkt->pts; |
2350 | 766 |
767 //FIXME just store one per syncpoint | |
768 if(flags & FLAG_KEY) | |
769 av_add_index_entry( | |
770 s->streams[pkt->stream_index], | |
771 nut->last_syncpoint_pos, | |
772 pkt->pts, | |
773 0, | |
774 0, | |
775 AVINDEX_KEYFRAME); | |
776 | |
2324 | 777 return 0; |
778 } | |
779 | |
2346
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
780 static int write_trailer(AVFormatContext *s){ |
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
781 NUTContext *nut= s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
782 ByteIOContext *bc= s->pb; |
2346
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
783 |
2359 | 784 while(nut->header_count<3) |
6072
0475ccdb762d
Make write_streamheader() and write_headers() accept an
stefano
parents:
6038
diff
changeset
|
785 write_headers(s, bc); |
2346
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
786 put_flush_packet(bc); |
5738 | 787 ff_nut_free_sp(nut); |
5729 | 788 av_freep(&nut->stream); |
789 av_freep(&nut->time_base); | |
2346
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
790 |
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
791 return 0; |
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
792 } |
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
793 |
2324 | 794 AVOutputFormat nut_muxer = { |
795 "nut", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3286
diff
changeset
|
796 NULL_IF_CONFIG_SMALL("NUT format"), |
2324 | 797 "video/x-nut", |
798 "nut", | |
799 sizeof(NUTContext), | |
4206 | 800 #if CONFIG_LIBVORBIS |
2324 | 801 CODEC_ID_VORBIS, |
4206 | 802 #elif CONFIG_LIBMP3LAME |
2324 | 803 CODEC_ID_MP3, |
804 #else | |
3623 | 805 CODEC_ID_MP2, |
2324 | 806 #endif |
807 CODEC_ID_MPEG4, | |
808 write_header, | |
809 write_packet, | |
2346
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
810 write_trailer, |
4567
963e3b76c7a6
Add AVFMT_VARIABLE_FPS to specify which muxers do not need duplicated frames.
michael
parents:
4520
diff
changeset
|
811 .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS, |
6038
d0ea87d82842
Define ff_nut_video_tags and make Nut muxer and demuxer set it in
stefano
parents:
6033
diff
changeset
|
812 .codec_tag = (const AVCodecTag * const []){ ff_codec_bmp_tags, ff_nut_video_tags, ff_codec_wav_tags, ff_nut_subtitle_tags, 0 }, |
5704
6b9c2a6d8fa4
Introduce metadata conversion table for NUT muxer and demuxer.
kostya
parents:
5058
diff
changeset
|
813 .metadata_conv = ff_nut_metadata_conv, |
2324 | 814 }; |