Mercurial > libavformat.hg
annotate nutenc.c @ 6118:6780dc315f36 libavformat
Remove support for pre-Haiku, non-POSIX, non-C99 BeOS variants.
BeOS support has been broken for many years and the "maintainer" of the port
has not reacted to countless requests to get the port fixed.
approved by Mans
author | diego |
---|---|
date | Thu, 10 Jun 2010 16:51:14 +0000 |
parents | be118b3b67a8 |
children | fa244b4fe683 |
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 | |
244 /** | |
245 * Gets the length in bytes which is needed to store val as v. | |
246 */ | |
247 static int get_length(uint64_t val){ | |
248 int i=1; | |
249 | |
250 while(val>>=7) | |
251 i++; | |
252 | |
253 return i; | |
254 } | |
255 | |
256 static void put_v(ByteIOContext *bc, uint64_t val){ | |
257 int i= get_length(val); | |
258 | |
259 while(--i>0) | |
260 put_byte(bc, 128 | (val>>(7*i))); | |
261 | |
262 put_byte(bc, val&127); | |
263 } | |
264 | |
4076 | 265 static void put_tt(NUTContext *nut, StreamContext *nus, ByteIOContext *bc, uint64_t val){ |
2342 | 266 val *= nut->time_base_count; |
267 val += nus->time_base - nut->time_base; | |
268 put_v(bc, val); | |
269 } | |
270 | |
2324 | 271 /** |
2393 | 272 * Stores a string as vb. |
2324 | 273 */ |
274 static void put_str(ByteIOContext *bc, const char *string){ | |
275 int len= strlen(string); | |
276 | |
277 put_v(bc, len); | |
278 put_buffer(bc, string, len); | |
279 } | |
280 | |
281 static void put_s(ByteIOContext *bc, int64_t val){ | |
282 put_v(bc, 2*FFABS(val) - (val>0)); | |
283 } | |
284 | |
285 #ifdef TRACE | |
286 static inline void put_v_trace(ByteIOContext *bc, uint64_t v, char *file, char *func, int line){ | |
2344 | 287 av_log(NULL, AV_LOG_DEBUG, "put_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line); |
2324 | 288 |
289 put_v(bc, v); | |
290 } | |
291 | |
292 static inline void put_s_trace(ByteIOContext *bc, int64_t v, char *file, char *func, int line){ | |
2344 | 293 av_log(NULL, AV_LOG_DEBUG, "put_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line); |
2324 | 294 |
295 put_s(bc, v); | |
296 } | |
297 #define put_v(bc, v) put_v_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__) | |
298 #define put_s(bc, v) put_s_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__) | |
299 #endif | |
300 | |
2340 | 301 //FIXME remove calculate_checksum |
2347 | 302 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
|
303 uint8_t *dyn_buf=NULL; |
4d1a56112d92
use a dynamic ByteIOContext instead of using the lavf buffer
michael
parents:
2330
diff
changeset
|
304 int dyn_size= url_close_dyn_buf(dyn_bc, &dyn_buf); |
2332 | 305 int forw_ptr= dyn_size + 4*calculate_checksum; |
2324 | 306 |
2332 | 307 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
|
308 init_checksum(bc, ff_crc04C11DB7_update, 0); |
2347 | 309 put_be64(bc, startcode); |
2332 | 310 put_v(bc, forw_ptr); |
311 if(forw_ptr > 4096) | |
312 put_le32(bc, get_checksum(bc)); | |
313 | |
2324 | 314 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
|
315 init_checksum(bc, ff_crc04C11DB7_update, 0); |
2331
4d1a56112d92
use a dynamic ByteIOContext instead of using the lavf buffer
michael
parents:
2330
diff
changeset
|
316 put_buffer(bc, dyn_buf, dyn_size); |
2324 | 317 if(calculate_checksum) |
2331
4d1a56112d92
use a dynamic ByteIOContext instead of using the lavf buffer
michael
parents:
2330
diff
changeset
|
318 put_le32(bc, get_checksum(bc)); |
2324 | 319 |
2331
4d1a56112d92
use a dynamic ByteIOContext instead of using the lavf buffer
michael
parents:
2330
diff
changeset
|
320 av_free(dyn_buf); |
2324 | 321 } |
322 | |
2329 | 323 static void write_mainheader(NUTContext *nut, ByteIOContext *bc){ |
3046 | 324 int i, j, tmp_pts, tmp_flags, tmp_stream, tmp_mul, tmp_size, tmp_fields, tmp_head_idx; |
325 int64_t tmp_match; | |
2324 | 326 |
2360
b2eeaa4df665
muxer should now be spec compliant (though it likely still contains bugs!)
michael
parents:
2359
diff
changeset
|
327 put_v(bc, 3); /* version */ |
2329 | 328 put_v(bc, nut->avf->nb_streams); |
3014
66fb9d4dea91
nut->max_distance was not set at all anywhere in the NUT muxer
ods15
parents:
3004
diff
changeset
|
329 put_v(bc, nut->max_distance); |
2324 | 330 put_v(bc, nut->time_base_count); |
331 | |
332 for(i=0; i<nut->time_base_count; i++){ | |
333 put_v(bc, nut->time_base[i].num); | |
334 put_v(bc, nut->time_base[i].den); | |
335 } | |
336 | |
337 tmp_pts=0; | |
338 tmp_mul=1; | |
339 tmp_stream=0; | |
3046 | 340 tmp_match= 1-(1LL<<62); |
341 tmp_head_idx= 0; | |
2324 | 342 for(i=0; i<256;){ |
343 tmp_fields=0; | |
344 tmp_size=0; | |
345 // tmp_res=0; | |
346 if(tmp_pts != nut->frame_code[i].pts_delta) tmp_fields=1; | |
347 if(tmp_mul != nut->frame_code[i].size_mul ) tmp_fields=2; | |
348 if(tmp_stream != nut->frame_code[i].stream_id) tmp_fields=3; | |
349 if(tmp_size != nut->frame_code[i].size_lsb ) tmp_fields=4; | |
350 // if(tmp_res != nut->frame_code[i].res ) tmp_fields=5; | |
3046 | 351 if(tmp_head_idx!=nut->frame_code[i].header_idx)tmp_fields=8; |
2324 | 352 |
353 tmp_pts = nut->frame_code[i].pts_delta; | |
354 tmp_flags = nut->frame_code[i].flags; | |
355 tmp_stream= nut->frame_code[i].stream_id; | |
356 tmp_mul = nut->frame_code[i].size_mul; | |
357 tmp_size = nut->frame_code[i].size_lsb; | |
358 // tmp_res = nut->frame_code[i].res; | |
3046 | 359 tmp_head_idx= nut->frame_code[i].header_idx; |
2324 | 360 |
361 for(j=0; i<256; j++,i++){ | |
362 if(i == 'N'){ | |
363 j--; | |
364 continue; | |
365 } | |
366 if(nut->frame_code[i].pts_delta != tmp_pts ) break; | |
367 if(nut->frame_code[i].flags != tmp_flags ) break; | |
368 if(nut->frame_code[i].stream_id != tmp_stream) break; | |
369 if(nut->frame_code[i].size_mul != tmp_mul ) break; | |
370 if(nut->frame_code[i].size_lsb != tmp_size+j) break; | |
371 // if(nut->frame_code[i].res != tmp_res ) break; | |
3046 | 372 if(nut->frame_code[i].header_idx!= tmp_head_idx) break; |
2324 | 373 } |
374 if(j != tmp_mul - tmp_size) tmp_fields=6; | |
375 | |
376 put_v(bc, tmp_flags); | |
377 put_v(bc, tmp_fields); | |
378 if(tmp_fields>0) put_s(bc, tmp_pts); | |
379 if(tmp_fields>1) put_v(bc, tmp_mul); | |
380 if(tmp_fields>2) put_v(bc, tmp_stream); | |
381 if(tmp_fields>3) put_v(bc, tmp_size); | |
382 if(tmp_fields>4) put_v(bc, 0 /*tmp_res*/); | |
383 if(tmp_fields>5) put_v(bc, j); | |
3046 | 384 if(tmp_fields>6) put_v(bc, tmp_match); |
385 if(tmp_fields>7) put_v(bc, tmp_head_idx); | |
386 } | |
387 put_v(bc, nut->header_count-1); | |
388 for(i=1; i<nut->header_count; i++){ | |
389 put_v(bc, nut->header_len[i]); | |
390 put_buffer(bc, nut->header[i], nut->header_len[i]); | |
2324 | 391 } |
2329 | 392 } |
2324 | 393 |
6072
0475ccdb762d
Make write_streamheader() and write_headers() accept an
stefano
parents:
6038
diff
changeset
|
394 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
|
395 NUTContext *nut = avctx->priv_data; |
3759
27537074f2a9
convert every muxer/demuxer to write/read sample_aspect_ratio from/to
aurel
parents:
3623
diff
changeset
|
396 AVCodecContext *codec = st->codec; |
2330 | 397 put_v(bc, i); |
398 switch(codec->codec_type){ | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5902
diff
changeset
|
399 case AVMEDIA_TYPE_VIDEO: put_v(bc, 0); break; |
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5902
diff
changeset
|
400 case AVMEDIA_TYPE_AUDIO: put_v(bc, 1); break; |
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5902
diff
changeset
|
401 case AVMEDIA_TYPE_SUBTITLE: put_v(bc, 2); break; |
2330 | 402 default : put_v(bc, 3); break; |
403 } | |
404 put_v(bc, 4); | |
405 if (codec->codec_tag){ | |
406 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
|
407 } else { |
be118b3b67a8
Make write_streamheader() log a message if there is no codec tag
stefano
parents:
6074
diff
changeset
|
408 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
|
409 return AVERROR(EINVAL); |
6075
be118b3b67a8
Make write_streamheader() log a message if there is no codec tag
stefano
parents:
6074
diff
changeset
|
410 } |
2330 | 411 |
2341 | 412 put_v(bc, nut->stream[i].time_base - nut->time_base); |
2330 | 413 put_v(bc, nut->stream[i].msb_pts_shift); |
414 put_v(bc, nut->stream[i].max_pts_distance); | |
415 put_v(bc, codec->has_b_frames); | |
416 put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */ | |
417 | |
418 put_v(bc, codec->extradata_size); | |
419 put_buffer(bc, codec->extradata, codec->extradata_size); | |
420 | |
421 switch(codec->codec_type){ | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5902
diff
changeset
|
422 case AVMEDIA_TYPE_AUDIO: |
2330 | 423 put_v(bc, codec->sample_rate); |
424 put_v(bc, 1); | |
425 put_v(bc, codec->channels); | |
426 break; | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5902
diff
changeset
|
427 case AVMEDIA_TYPE_VIDEO: |
2330 | 428 put_v(bc, codec->width); |
429 put_v(bc, codec->height); | |
2363 | 430 |
3759
27537074f2a9
convert every muxer/demuxer to write/read sample_aspect_ratio from/to
aurel
parents:
3623
diff
changeset
|
431 if(st->sample_aspect_ratio.num<=0 || st->sample_aspect_ratio.den<=0){ |
2363 | 432 put_v(bc, 0); |
433 put_v(bc, 0); | |
434 }else{ | |
3759
27537074f2a9
convert every muxer/demuxer to write/read sample_aspect_ratio from/to
aurel
parents:
3623
diff
changeset
|
435 put_v(bc, st->sample_aspect_ratio.num); |
27537074f2a9
convert every muxer/demuxer to write/read sample_aspect_ratio from/to
aurel
parents:
3623
diff
changeset
|
436 put_v(bc, st->sample_aspect_ratio.den); |
2363 | 437 } |
2330 | 438 put_v(bc, 0); /* csp type -- unknown */ |
439 break; | |
440 default: | |
441 break; | |
442 } | |
443 return 0; | |
444 } | |
445 | |
3004 | 446 static int add_info(ByteIOContext *bc, const char *type, const char *value){ |
2358 | 447 put_str(bc, type); |
448 put_s(bc, -1); | |
449 put_str(bc, value); | |
450 return 1; | |
451 } | |
452 | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
453 static int write_globalinfo(NUTContext *nut, ByteIOContext *bc){ |
2358 | 454 AVFormatContext *s= nut->avf; |
5704
6b9c2a6d8fa4
Introduce metadata conversion table for NUT muxer and demuxer.
kostya
parents:
5058
diff
changeset
|
455 AVMetadataTag *t = NULL; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
456 ByteIOContext *dyn_bc; |
2358 | 457 uint8_t *dyn_buf=NULL; |
458 int count=0, dyn_size; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
459 int ret = url_open_dyn_buf(&dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
460 if(ret < 0) |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
461 return ret; |
2358 | 462 |
5704
6b9c2a6d8fa4
Introduce metadata conversion table for NUT muxer and demuxer.
kostya
parents:
5058
diff
changeset
|
463 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
|
464 count += add_info(dyn_bc, t->key, t->value); |
2358 | 465 |
466 put_v(bc, 0); //stream_if_plus1 | |
467 put_v(bc, 0); //chapter_id | |
468 put_v(bc, 0); //timestamp_start | |
469 put_v(bc, 0); //length | |
470 | |
471 put_v(bc, count); | |
472 | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
473 dyn_size= url_close_dyn_buf(dyn_bc, &dyn_buf); |
2358 | 474 put_buffer(bc, dyn_buf, dyn_size); |
475 av_free(dyn_buf); | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
476 return 0; |
2358 | 477 } |
478 | |
3120
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
479 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
|
480 AVFormatContext *s= nut->avf; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
481 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
|
482 ByteIOContext *dyn_bc; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
483 uint8_t *dyn_buf=NULL; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
484 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
|
485 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
|
486 if(ret < 0) |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
487 return ret; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
488 |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
489 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
|
490 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
|
491 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
|
492 } |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
493 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
|
494 |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
495 if (count) { |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
496 put_v(bc, stream_id + 1); //stream_id_plus1 |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
497 put_v(bc, 0); //chapter_id |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
498 put_v(bc, 0); //timestamp_start |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
499 put_v(bc, 0); //length |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
500 |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
501 put_v(bc, count); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
502 |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
503 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
|
504 } |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
505 |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
506 av_free(dyn_buf); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
507 return count; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
508 } |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
509 |
6072
0475ccdb762d
Make write_streamheader() and write_headers() accept an
stefano
parents:
6038
diff
changeset
|
510 static int write_headers(AVFormatContext *avctx, ByteIOContext *bc){ |
0475ccdb762d
Make write_streamheader() and write_headers() accept an
stefano
parents:
6038
diff
changeset
|
511 NUTContext *nut = avctx->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
512 ByteIOContext *dyn_bc; |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
513 int i, ret; |
2345 | 514 |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
515 ret = url_open_dyn_buf(&dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
516 if(ret < 0) |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
517 return ret; |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
518 write_mainheader(nut, dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
519 put_packet(nut, bc, dyn_bc, 1, MAIN_STARTCODE); |
2345 | 520 |
521 for (i=0; i < nut->avf->nb_streams; i++){ | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
522 ret = url_open_dyn_buf(&dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
523 if(ret < 0) |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
524 return ret; |
6073
b9ddee1ca18c
Make write_header() and write_header() return an error code in case of
stefano
parents:
6072
diff
changeset
|
525 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
|
526 return ret; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
527 put_packet(nut, bc, dyn_bc, 1, STREAM_STARTCODE); |
2345 | 528 } |
2358 | 529 |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
530 ret = url_open_dyn_buf(&dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
531 if(ret < 0) |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
532 return ret; |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
533 write_globalinfo(nut, dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
534 put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE); |
2359 | 535 |
3120
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
536 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
|
537 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
|
538 if(ret < 0) |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
539 return ret; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
540 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
|
541 if (ret < 0) |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
542 return ret; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
543 if (ret > 0) |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
544 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
|
545 else { |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
546 uint8_t* buf; |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
547 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
|
548 av_free(buf); |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
549 } |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
550 } |
ea5623a8efde
Add 'disposition' bitfield to AVStream and use it for both muxing and demuxing
eugeni
parents:
3112
diff
changeset
|
551 |
2359 | 552 nut->last_syncpoint_pos= INT_MIN; |
553 nut->header_count++; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
554 return 0; |
2345 | 555 } |
556 | |
2329 | 557 static int write_header(AVFormatContext *s){ |
558 NUTContext *nut = s->priv_data; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
559 ByteIOContext *bc = s->pb; |
6073
b9ddee1ca18c
Make write_header() and write_header() return an error code in case of
stefano
parents:
6072
diff
changeset
|
560 int i, j, ret; |
2329 | 561 |
562 nut->avf= s; | |
563 | |
564 nut->stream = av_mallocz(sizeof(StreamContext)*s->nb_streams); | |
565 nut->time_base= av_mallocz(sizeof(AVRational )*s->nb_streams); | |
566 | |
567 for(i=0; i<s->nb_streams; i++){ | |
568 AVStream *st= s->streams[i]; | |
569 int ssize; | |
570 AVRational time_base; | |
571 ff_parse_specific_params(st->codec, &time_base.den, &ssize, &time_base.num); | |
572 | |
573 av_set_pts_info(st, 64, time_base.num, time_base.den); | |
574 | |
575 for(j=0; j<nut->time_base_count; j++){ | |
576 if(!memcmp(&time_base, &nut->time_base[j], sizeof(AVRational))){ | |
577 break; | |
578 } | |
579 } | |
580 nut->time_base[j]= time_base; | |
581 nut->stream[i].time_base= &nut->time_base[j]; | |
582 if(j==nut->time_base_count) | |
583 nut->time_base_count++; | |
584 | |
585 if(av_q2d(time_base) >= 0.001) | |
586 nut->stream[i].msb_pts_shift = 7; | |
587 else | |
588 nut->stream[i].msb_pts_shift = 14; | |
589 nut->stream[i].max_pts_distance= FFMAX(1/av_q2d(time_base), 1); | |
590 } | |
591 | |
3014
66fb9d4dea91
nut->max_distance was not set at all anywhere in the NUT muxer
ods15
parents:
3004
diff
changeset
|
592 nut->max_distance = MAX_DISTANCE; |
3046 | 593 build_elision_headers(s); |
2329 | 594 build_frame_code(s); |
595 assert(nut->frame_code['N'].flags == FLAG_INVALID); | |
596 | |
597 put_buffer(bc, ID_STRING, strlen(ID_STRING)); | |
598 put_byte(bc, 0); | |
599 | |
6073
b9ddee1ca18c
Make write_header() and write_header() return an error code in case of
stefano
parents:
6072
diff
changeset
|
600 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
|
601 return ret; |
2325 | 602 |
2324 | 603 put_flush_packet(bc); |
604 | |
2359 | 605 //FIXME index |
2324 | 606 |
607 return 0; | |
608 } | |
609 | |
2343 | 610 static int get_needed_flags(NUTContext *nut, StreamContext *nus, FrameCode *fc, AVPacket *pkt){ |
611 int flags= 0; | |
612 | |
5913
11bb10c37225
Replace all occurences of PKT_FLAG_KEY with AV_PKT_FLAG_KEY.
cehoyos
parents:
5910
diff
changeset
|
613 if(pkt->flags & AV_PKT_FLAG_KEY ) flags |= FLAG_KEY; |
2343 | 614 if(pkt->stream_index != fc->stream_id ) flags |= FLAG_STREAM_ID; |
615 if(pkt->size / fc->size_mul ) flags |= FLAG_SIZE_MSB; | |
616 if(pkt->pts - nus->last_pts != fc->pts_delta) flags |= FLAG_CODED_PTS; | |
617 if(pkt->size > 2*nut->max_distance ) flags |= FLAG_CHECKSUM; | |
618 if(FFABS(pkt->pts - nus->last_pts) | |
619 > nus->max_pts_distance) flags |= FLAG_CHECKSUM; | |
3046 | 620 if( pkt->size < nut->header_len[fc->header_idx] |
621 || (pkt->size > 4096 && fc->header_idx) | |
622 || memcmp(pkt->data, nut->header[fc->header_idx], nut->header_len[fc->header_idx])) | |
623 flags |= FLAG_HEADER_IDX; | |
2343 | 624 |
2371 | 625 return flags | (fc->flags & FLAG_CODED); |
2343 | 626 } |
627 | |
3046 | 628 static int find_best_header_idx(NUTContext *nut, AVPacket *pkt){ |
629 int i; | |
630 int best_i = 0; | |
631 int best_len= 0; | |
632 | |
633 if(pkt->size > 4096) | |
634 return 0; | |
635 | |
636 for(i=1; i<nut->header_count; i++){ | |
637 if( pkt->size >= nut->header_len[i] | |
638 && nut->header_len[i] > best_len | |
639 && !memcmp(pkt->data, nut->header[i], nut->header_len[i])){ | |
640 best_i= i; | |
641 best_len= nut->header_len[i]; | |
642 } | |
643 } | |
644 return best_i; | |
645 } | |
646 | |
2324 | 647 static int write_packet(AVFormatContext *s, AVPacket *pkt){ |
2343 | 648 NUTContext *nut = s->priv_data; |
649 StreamContext *nus= &nut->stream[pkt->stream_index]; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
650 ByteIOContext *bc = s->pb, *dyn_bc; |
2343 | 651 FrameCode *fc; |
652 int64_t coded_pts; | |
3046 | 653 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
|
654 int key_frame = !!(pkt->flags & AV_PKT_FLAG_KEY); |
2343 | 655 int store_sp=0; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
656 int ret; |
2343 | 657 |
3508 | 658 if(pkt->pts < 0) |
659 return -1; | |
660 | |
2359 | 661 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
|
662 write_headers(s, bc); |
2359 | 663 |
3015
db8d14740060
Fix intented algo in syncpoint writing before keyframes in NUT muxer
ods15
parents:
3014
diff
changeset
|
664 if(key_frame && !(nus->last_flags & FLAG_KEY)) |
2343 | 665 store_sp= 1; |
666 | |
667 if(pkt->size + 30/*FIXME check*/ + url_ftell(bc) >= nut->last_syncpoint_pos + nut->max_distance) | |
668 store_sp= 1; | |
669 | |
2393 | 670 //FIXME: Ensure store_sp is 1 in the first place. |
2343 | 671 |
672 if(store_sp){ | |
4076 | 673 Syncpoint *sp, dummy= {.pos= INT64_MAX}; |
2350 | 674 |
2343 | 675 ff_nut_reset_ts(nut, *nus->time_base, pkt->dts); |
2350 | 676 for(i=0; i<s->nb_streams; i++){ |
677 AVStream *st= s->streams[i]; | |
3016
eac2648449a5
back_ptr calculation used wrong timebase when searching for back syncpoint
ods15
parents:
3015
diff
changeset
|
678 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
|
679 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
|
680 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
|
681 AV_ROUND_DOWN); |
eac2648449a5
back_ptr calculation used wrong timebase when searching for back syncpoint
ods15
parents:
3015
diff
changeset
|
682 int index= av_index_search_timestamp(st, dts_tb, AVSEEK_FLAG_BACKWARD); |
2939 | 683 if(index>=0) dummy.pos= FFMIN(dummy.pos, st->index_entries[index].pos); |
2350 | 684 } |
2939 | 685 if(dummy.pos == INT64_MAX) |
686 dummy.pos= 0; | |
5902 | 687 sp= av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp, |
688 NULL); | |
2343 | 689 |
690 nut->last_syncpoint_pos= url_ftell(bc); | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
691 ret = url_open_dyn_buf(&dyn_bc); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
692 if(ret < 0) |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
693 return ret; |
4076 | 694 put_tt(nut, nus, dyn_bc, pkt->dts); |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
695 put_v(dyn_bc, sp ? (nut->last_syncpoint_pos - sp->pos)>>4 : 0); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
696 put_packet(nut, bc, dyn_bc, 1, SYNCPOINT_STARTCODE); |
2350 | 697 |
698 ff_nut_add_sp(nut, nut->last_syncpoint_pos, 0/*unused*/, pkt->dts); | |
2343 | 699 } |
700 assert(nus->last_pts != AV_NOPTS_VALUE); | |
701 | |
702 coded_pts = pkt->pts & ((1<<nus->msb_pts_shift)-1); | |
703 if(ff_lsb2full(nus, coded_pts) != pkt->pts) | |
704 coded_pts= pkt->pts + (1<<nus->msb_pts_shift); | |
705 | |
3046 | 706 best_header_idx= find_best_header_idx(nut, pkt); |
707 | |
2343 | 708 best_length=INT_MAX; |
709 frame_code= -1; | |
710 for(i=0; i<256; i++){ | |
711 int length= 0; | |
712 FrameCode *fc= &nut->frame_code[i]; | |
713 int flags= fc->flags; | |
714 | |
715 if(flags & FLAG_INVALID) | |
716 continue; | |
717 needed_flags= get_needed_flags(nut, nus, fc, pkt); | |
718 | |
719 if(flags & FLAG_CODED){ | |
720 length++; | |
2372 | 721 flags = needed_flags; |
2343 | 722 } |
723 | |
724 if((flags & needed_flags) != needed_flags) | |
725 continue; | |
726 | |
727 if((flags ^ needed_flags) & FLAG_KEY) | |
728 continue; | |
729 | |
730 if(flags & FLAG_STREAM_ID) | |
731 length+= get_length(pkt->stream_index); | |
732 | |
733 if(pkt->size % fc->size_mul != fc->size_lsb) | |
734 continue; | |
735 if(flags & FLAG_SIZE_MSB) | |
736 length += get_length(pkt->size / fc->size_mul); | |
737 | |
738 if(flags & FLAG_CHECKSUM) | |
739 length+=4; | |
740 | |
741 if(flags & FLAG_CODED_PTS) | |
742 length += get_length(coded_pts); | |
743 | |
3046 | 744 if( (flags & FLAG_CODED) |
745 && nut->header_len[best_header_idx] > nut->header_len[fc->header_idx]+1){ | |
746 flags |= FLAG_HEADER_IDX; | |
747 } | |
748 | |
749 if(flags & FLAG_HEADER_IDX){ | |
750 length += 1 - nut->header_len[best_header_idx]; | |
751 }else{ | |
752 length -= nut->header_len[fc->header_idx]; | |
753 } | |
754 | |
2343 | 755 length*=4; |
756 length+= !(flags & FLAG_CODED_PTS); | |
757 length+= !(flags & FLAG_CHECKSUM); | |
758 | |
759 if(length < best_length){ | |
760 best_length= length; | |
761 frame_code=i; | |
762 } | |
763 } | |
764 assert(frame_code != -1); | |
765 fc= &nut->frame_code[frame_code]; | |
766 flags= fc->flags; | |
767 needed_flags= get_needed_flags(nut, nus, fc, pkt); | |
3046 | 768 header_idx= fc->header_idx; |
2343 | 769 |
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
|
770 init_checksum(bc, ff_crc04C11DB7_update, 0); |
2343 | 771 put_byte(bc, frame_code); |
772 if(flags & FLAG_CODED){ | |
773 put_v(bc, (flags^needed_flags) & ~(FLAG_CODED)); | |
774 flags = needed_flags; | |
775 } | |
776 if(flags & FLAG_STREAM_ID) put_v(bc, pkt->stream_index); | |
777 if(flags & FLAG_CODED_PTS) put_v(bc, coded_pts); | |
778 if(flags & FLAG_SIZE_MSB) put_v(bc, pkt->size / fc->size_mul); | |
3046 | 779 if(flags & FLAG_HEADER_IDX) put_v(bc, header_idx= best_header_idx); |
2343 | 780 |
781 if(flags & FLAG_CHECKSUM) put_le32(bc, get_checksum(bc)); | |
782 else get_checksum(bc); | |
783 | |
3046 | 784 put_buffer(bc, pkt->data + nut->header_len[header_idx], pkt->size - nut->header_len[header_idx]); |
2343 | 785 nus->last_flags= flags; |
3047 | 786 nus->last_pts= pkt->pts; |
2350 | 787 |
788 //FIXME just store one per syncpoint | |
789 if(flags & FLAG_KEY) | |
790 av_add_index_entry( | |
791 s->streams[pkt->stream_index], | |
792 nut->last_syncpoint_pos, | |
793 pkt->pts, | |
794 0, | |
795 0, | |
796 AVINDEX_KEYFRAME); | |
797 | |
2324 | 798 return 0; |
799 } | |
800 | |
2346
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
801 static int write_trailer(AVFormatContext *s){ |
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
802 NUTContext *nut= s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2683
diff
changeset
|
803 ByteIOContext *bc= s->pb; |
2346
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
804 |
2359 | 805 while(nut->header_count<3) |
6072
0475ccdb762d
Make write_streamheader() and write_headers() accept an
stefano
parents:
6038
diff
changeset
|
806 write_headers(s, bc); |
2346
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
807 put_flush_packet(bc); |
5738 | 808 ff_nut_free_sp(nut); |
5729 | 809 av_freep(&nut->stream); |
810 av_freep(&nut->time_base); | |
2346
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
811 |
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
812 return 0; |
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
813 } |
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
814 |
2324 | 815 AVOutputFormat nut_muxer = { |
816 "nut", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3286
diff
changeset
|
817 NULL_IF_CONFIG_SMALL("NUT format"), |
2324 | 818 "video/x-nut", |
819 "nut", | |
820 sizeof(NUTContext), | |
4206 | 821 #if CONFIG_LIBVORBIS |
2324 | 822 CODEC_ID_VORBIS, |
4206 | 823 #elif CONFIG_LIBMP3LAME |
2324 | 824 CODEC_ID_MP3, |
825 #else | |
3623 | 826 CODEC_ID_MP2, |
2324 | 827 #endif |
828 CODEC_ID_MPEG4, | |
829 write_header, | |
830 write_packet, | |
2346
cbcd840cf971
store headers twice (getting closer to spec compliance ...)
michael
parents:
2345
diff
changeset
|
831 write_trailer, |
4567
963e3b76c7a6
Add AVFMT_VARIABLE_FPS to specify which muxers do not need duplicated frames.
michael
parents:
4520
diff
changeset
|
832 .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
|
833 .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
|
834 .metadata_conv = ff_nut_metadata_conv, |
2324 | 835 }; |