1 #include "funcprotos.h"
5 #include "vorbis/vorbisenc.h"
7 // Attempts to read more samples than this will crash
8 #define OUTPUT_ALLOCATION 0x100000
9 #define CLAMP(x, y, z) ((x) = ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x))))
17 int encode_initialized
;
18 ogg_stream_state enc_os
;
22 vorbis_comment enc_vc
;
23 vorbis_dsp_state enc_vd
;
25 // Number of samples written to disk
27 // Number of bytes written to disk
28 int64_t encoded_bytes
;
31 // Number of samples encoded into the chunk
36 ogg_sync_state dec_oy
; /* sync and verify incoming physical bitstream */
37 ogg_stream_state dec_os
; /* take physical pages, weld into a logical
39 ogg_page dec_og
; /* one Ogg bitstream page. Vorbis packets are inside */
40 ogg_packet dec_op
; /* one raw packet of data for decode */
42 vorbis_info dec_vi
; /* struct that stores all the static vorbis bitstream
44 vorbis_comment dec_vc
; /* struct that stores all the bitstream user comments */
45 vorbis_dsp_state dec_vd
; /* central working state for the packet->PCM decoder */
46 vorbis_block dec_vb
; /* local working space for packet->PCM decode */
48 unsigned int dec_current_serialno
;
49 int decode_initialized
;
52 // Number of last sample relative to file
53 int64_t output_position
;
54 // Number of last sample relative to output buffer
56 // Number of samples in output buffer
58 // Number of samples allocated in output buffer
59 long output_allocated
;
60 // Current reading position in file
62 // Number of samples decoded in the current chunk
64 } quicktime_vorbis_codec_t
;
67 /* =================================== public for vorbis */
69 static int delete_codec(quicktime_audio_map_t
*atrack
)
71 quicktime_vorbis_codec_t
*codec
= ((quicktime_codec_t
*)atrack
->codec
)->priv
;
74 if(codec
->encode_initialized
)
76 ogg_stream_clear(&codec
->enc_os
);
77 vorbis_block_clear(&codec
->enc_vb
);
78 vorbis_dsp_clear(&codec
->enc_vd
);
79 vorbis_comment_clear(&codec
->enc_vc
);
80 vorbis_info_clear(&codec
->enc_vi
);
83 if(codec
->decode_initialized
)
87 for(i
= 0; i
< atrack
->channels
; i
++)
88 free(codec
->output
[i
]);
93 ogg_stream_clear(&codec
->dec_os
);
94 vorbis_block_clear(&codec
->dec_vb
);
95 vorbis_dsp_clear(&codec
->dec_vd
);
96 vorbis_comment_clear(&codec
->dec_vc
);
97 vorbis_info_clear(&codec
->dec_vi
);
108 // Buffer fragment should be bigger then largest page header so
109 // all lacing bytes can be decoded.
110 #define BUFFER_FRAGMENT 4096
112 // Calculate chunk length from OggS headers. This is the worst case
113 // but it's better not to assume libogg is going to do anything for us.
115 #define SEGMENT_OFFSET 0x1a
116 #define LACE_OFFSET 0x1b
117 static int chunk_len(quicktime_t
*file
, int64_t offset
, int64_t next_chunk
)
120 unsigned char buffer
[BUFFER_FRAGMENT
];
122 int segment_count
= 0;
123 int segment_size
= 0;
128 while(offset
< next_chunk
)
130 quicktime_set_position(file
, offset
);
131 result
= !quicktime_read_data(file
, buffer
, BUFFER_FRAGMENT
);
138 if(memcmp(buffer
, "OggS", 4))
146 // Decode size of OggS page
147 segment_count
= buffer
[SEGMENT_OFFSET
];
149 // Decode one segment at a time
152 while(segment_count
> 0)
154 page_size
+= buffer
[i
++];
157 accum
+= i
+ page_size
;
158 offset
+= i
+ page_size
;
166 // Calculates the chunk size based on ogg pages.
167 #define READ_CHUNK(chunk) \
169 int64_t offset1 = quicktime_chunk_to_offset(file, trak, (chunk)); \
170 int64_t offset2 = quicktime_chunk_to_offset(file, trak, (chunk) + 1); \
172 if(offset2 == offset1) \
176 size = chunk_len(file, offset1, \
177 offset2 > offset1 ? offset2 : offset1 + 0xfffff); \
179 buffer = ogg_sync_buffer(&codec->dec_oy, size); \
180 quicktime_set_position(file, offset1); \
181 result = !quicktime_read_data(file, buffer, size); \
182 ogg_sync_wrote(&codec->dec_oy, size); \
184 /* printf("READ_CHUNK size=%d\n", size); */ \
185 /* printf("%llx %x: ", quicktime_chunk_to_offset(file, trak, (chunk)), size); */ \
186 /* for(i = 0; i < 16; i++) */ \
187 /* printf("%02x ", buffer[i]); */ \
188 /* printf("result=%d\n", result); */ \
194 static int decode(quicktime_t
*file
,
204 quicktime_audio_map_t
*track_map
= &(file
->atracks
[track
]);
205 quicktime_trak_t
*trak
= track_map
->track
;
206 quicktime_vorbis_codec_t
*codec
= ((quicktime_codec_t
*)track_map
->codec
)->priv
;
207 long current_position
= track_map
->current_position
;
208 long end_position
= current_position
+ samples
;
209 unsigned char *buffer
;
210 // End of data in ogg buffer
218 if(samples
> OUTPUT_ALLOCATION
)
219 printf("vorbis.c decode: can't read more than %p samples at a time.\n", OUTPUT_ALLOCATION
);
223 if(output_i
) bzero(output_i
, sizeof(int16_t) * samples
);
224 if(output_f
) bzero(output_f
, sizeof(float) * samples
);
232 // Seeked outside output buffer's range or not initialized: restart
233 if(current_position
< codec
->output_position
- codec
->output_size
||
234 current_position
> codec
->output_position
||
235 !codec
->decode_initialized
)
238 quicktime_chunk_of_sample(&codec
->output_position
,
242 // We know the first ogg packet in the chunk has a pcm_offset from the encoding.
244 codec
->output_size
= 0;
245 codec
->output_end
= 0;
246 codec
->chunk_samples
= 0;
251 // Initialize and load initial buffer for decoding
252 if(!codec
->decode_initialized
)
255 codec
->decode_initialized
= 1;
257 codec
->output
= malloc(sizeof(float*) * track_map
->channels
);
258 for(i
= 0; i
< track_map
->channels
; i
++)
260 codec
->output
[i
] = malloc(sizeof(float) * OUTPUT_ALLOCATION
);
263 codec
->output_allocated
= OUTPUT_ALLOCATION
;
265 ogg_sync_init(&codec
->dec_oy
); /* Now we can read pages */
270 READ_CHUNK(init_chunk
);
273 if(ogg_sync_pageout(&codec
->dec_oy
, &codec
->dec_og
)!=1)
275 fprintf(stderr
, "decode: ogg_sync_pageout: Must not be Vorbis data\n");
280 ogg_stream_init(&codec
->dec_os
, ogg_page_serialno(&codec
->dec_og
));
281 vorbis_info_init(&codec
->dec_vi
);
282 vorbis_comment_init(&codec
->dec_vc
);
284 if(ogg_stream_pagein(&codec
->dec_os
, &codec
->dec_og
) < 0)
286 fprintf(stderr
,"decode: ogg_stream_pagein: stream version mismatch perhaps.\n");
290 if(ogg_stream_packetout(&codec
->dec_os
, &codec
->dec_op
) != 1)
292 fprintf(stderr
, "decode: ogg_stream_packetout: Must not be Vorbis data\n");
296 if(vorbis_synthesis_headerin(&codec
->dec_vi
, &codec
->dec_vc
, &codec
->dec_op
) < 0)
298 fprintf(stderr
, "decode: vorbis_synthesis_headerin: not a vorbis header\n");
308 result
= ogg_sync_pageout(&codec
->dec_oy
, &codec
->dec_og
);
309 if(result
== 0) break;
313 ogg_stream_pagein(&codec
->dec_os
, &codec
->dec_og
);
317 result
= ogg_stream_packetout(&codec
->dec_os
, &codec
->dec_op
);
319 if(result
== 0) break;
323 fprintf(stderr
, "decode: ogg_stream_packetout: corrupt secondary header\n");
327 vorbis_synthesis_headerin(&codec
->dec_vi
, &codec
->dec_vc
, &codec
->dec_op
);
339 READ_CHUNK(init_chunk
);
343 // Header should never span more than one chunk so assume it's done here
346 vorbis_synthesis_init(&codec
->dec_vd
, &codec
->dec_vi
);
347 vorbis_block_init(&codec
->dec_vd
, &codec
->dec_vb
);
349 // Also the first chunk needed in decoding so don't reread after this.
350 if(codec
->chunk
== init_chunk
- 1)
360 // Don't already have initial chunk from header
363 // Get initial chunk for decoding at new location
365 /* clear out decoding machine state */
366 ogg_stream_clear(&codec
->dec_os
);
367 vorbis_dsp_clear(&codec
->dec_vd
);
368 vorbis_block_clear(&codec
->dec_vb
);
369 ogg_sync_reset(&codec
->dec_oy
);
371 ogg_stream_init(&codec
->dec_os
, ogg_page_serialno(&codec
->dec_og
));
372 ogg_sync_init(&codec
->dec_oy
);
373 vorbis_synthesis_init(&codec
->dec_vd
, &codec
->dec_vi
);
374 vorbis_block_init(&codec
->dec_vd
, &codec
->dec_vb
);
377 READ_CHUNK(codec
->chunk
);
383 // Assume the chunk exists by now and rely on libogg to say if it's out of
397 // Read chunks until output buffer is on or after end_position
399 while(codec
->output_position
< end_position
)
403 // Read chunk to decode if it hasn't been read yet.
406 codec
->chunk_samples
= 0;
408 READ_CHUNK(codec
->chunk
);
416 result
= ogg_sync_pageout(&codec
->dec_oy
, &codec
->dec_og
);
424 // Need more data from chunk
431 // This stage checks for OggS and a checksum error.
432 // It doesn't tell if it's the end of a chunk. Need to manually parse OggS
433 // pages to figure out how big the chunk is.
436 //printf("ogg_sync_pageout=-1\n");
441 ogg_stream_pagein(&codec
->dec_os
, &codec
->dec_og
);
447 //printf("decode 7\n");
448 result
= ogg_stream_packetout(&codec
->dec_os
, &codec
->dec_op
);
450 //printf("decode 8 %d\n", result);
453 //printf("ogg_stream_packetout=0\n");
458 // This stage doesn't check for OggS.
461 //printf("ogg_stream_packetout=-1\n");
473 if(vorbis_synthesis(&codec
->dec_vb
, &codec
->dec_op
) == 0)
475 vorbis_synthesis_blockin(&codec
->dec_vd
,
480 while((result
= vorbis_synthesis_pcmout(&codec
->dec_vd
, &pcm
)) > 0)
482 //printf("vorbis_synthesis_pcmout=%x\n", result);
483 for(i
= 0; i
< track_map
->channels
; i
++)
485 float *output_channel
= codec
->output
[i
];
486 float *input_channel
= pcm
[i
];
487 int k
= codec
->output_end
;
489 for(j
= 0; j
< result
; j
++)
491 output_channel
[k
++] = input_channel
[j
];
492 if(k
>= codec
->output_allocated
)
496 if(i
== track_map
->channels
- 1)
497 codec
->output_end
= k
;
499 //printf("codec->output_end = %d\n", codec->output_end);
501 codec
->output_position
+= result
;
502 codec
->output_size
+= result
;
503 codec
->chunk_samples
+= result
;
504 if(codec
->output_size
> codec
->output_allocated
)
505 codec
->output_size
= codec
->output_allocated
;
506 vorbis_synthesis_read(&codec
->dec_vd
, result
);
509 //printf("decode 11\n");
512 // Reset end of page so it isn't interpreted as an end of chunk
521 //printf("decode 12 got=%x\n", codec->chunk_samples);
528 while(codec
->output_position
< end_position
)
530 for(i
= 0; i
< track_map
->channels
; i
++)
531 codec
->output
[i
][codec
->output_end
] = 0;
534 if(codec
->output_end
>= codec
->output_allocated
)
535 codec
->output_end
= 0;
536 codec
->output_position
++;
538 //printf("decode 15\n");
541 //printf("decode 2 codec->output_position=%lld codec->output_end=%d codec->output_size=%d\n",
542 // codec->output_position, codec->output_end, codec->output_size);
544 current_position
= track_map
->current_position
;
545 i
= codec
->output_end
- (codec
->output_position
- current_position
);
547 while(i
< 0) i
+= codec
->output_allocated
;
548 pcm
= codec
->output
[channel
];
552 for( ; j
< samples
; j
++)
554 int sample
= pcm
[i
] * 32767;
555 CLAMP(sample
, -32768, 32767);
556 output_i
[j
] = sample
;
559 if(i
>= codec
->output_allocated
) i
= 0;
565 for( ; j
< samples
; j
++)
567 output_f
[j
] = pcm
[i
];
569 if(i
>= codec
->output_allocated
) i
= 0;
572 //printf("decode 16\n");
599 int eos = !ogg_stream_flush(&codec->enc_os, &codec->enc_og); \
605 quicktime_write_chunk_header(file, trak, &chunk_atom); \
608 result = !quicktime_write_data(file, codec->enc_og.header, codec->enc_og.header_len); \
609 size += codec->enc_og.header_len; \
613 result = !quicktime_write_data(file, codec->enc_og.body, codec->enc_og.body_len); \
614 size += codec->enc_og.body_len; \
624 while(vorbis_analysis_blockout(&codec->enc_vd, &codec->enc_vb) == 1) \
626 vorbis_analysis(&codec->enc_vb, &codec->enc_op); \
627 vorbis_bitrate_addblock(&codec->enc_vb); \
628 while(vorbis_bitrate_flushpacket(&codec->enc_vd, &codec->enc_op)) \
630 ogg_stream_packetin(&codec->enc_os, &codec->enc_op); \
634 if(!ogg_stream_pageout(&codec->enc_os, &codec->enc_og)) break; \
640 quicktime_write_chunk_header(file, trak, &chunk_atom); \
642 result = !quicktime_write_data(file, codec->enc_og.header, codec->enc_og.header_len); \
643 size += codec->enc_og.header_len; \
647 result = !quicktime_write_data(file, codec->enc_og.body, codec->enc_og.body_len); \
648 size += codec->enc_og.body_len; \
651 if(ogg_page_eos(&codec->enc_og)) break; \
657 static int encode(quicktime_t
*file
,
664 int64_t offset
= quicktime_position(file
);
665 quicktime_audio_map_t
*track_map
= &(file
->atracks
[track
]);
666 quicktime_trak_t
*trak
= track_map
->track
;
667 quicktime_vorbis_codec_t
*codec
= ((quicktime_codec_t
*)track_map
->codec
)->priv
;
668 int samplerate
= trak
->mdia
.minf
.stbl
.stsd
.table
[0].sample_rate
;
671 int chunk_started
= 0;
672 quicktime_atom_t chunk_atom
;
675 if(samplerate
< 32000)
677 printf("encode: sample rate %d not supported.\n", samplerate
);
685 if(!codec
->encode_initialized
)
688 ogg_packet header_comm
;
689 ogg_packet header_code
;
692 codec
->encode_initialized
= 1;
694 trak
->mdia
.minf
.stbl
.stsd
.table
[0].sample_size
= 0;
695 vorbis_info_init(&codec
->enc_vi
);
699 result
= vorbis_encode_setup_managed(&codec
->enc_vi
,
703 codec
->nominal_bitrate
,
705 result
|= vorbis_encode_ctl(&codec
->enc_vi
, OV_ECTL_RATEMANAGE_AVG
, NULL
);
706 result
|= vorbis_encode_setup_init(&codec
->enc_vi
);
710 vorbis_encode_init(&codec
->enc_vi
,
714 codec
->nominal_bitrate
,
719 vorbis_comment_init(&codec
->enc_vc
);
720 vorbis_analysis_init(&codec
->enc_vd
, &codec
->enc_vi
);
721 vorbis_block_init(&codec
->enc_vd
, &codec
->enc_vb
);
723 ogg_stream_init(&codec
->enc_os
, rand());
726 vorbis_analysis_headerout(&codec
->enc_vd
,
732 ogg_stream_packetin(&codec
->enc_os
, &header
);
733 ogg_stream_packetin(&codec
->enc_os
, &header_comm
);
734 ogg_stream_packetin(&codec
->enc_os
, &header_code
);
739 output
= vorbis_analysis_buffer(&codec
->enc_vd
, samples
);
744 for(i
= 0; i
< track_map
->channels
; i
++)
746 for(j
= 0; j
< samples
; j
++)
748 output
[i
][j
] = (float)input_i
[i
][j
] / (float)32768;
756 for(i
= 0; i
< track_map
->channels
; i
++)
758 memcpy(output
[i
], input_f
[i
], sizeof(float) * samples
);
762 vorbis_analysis_wrote(&codec
->enc_vd
, samples
);
766 codec
->next_chunk_size
+= samples
;
771 int new_encoded_samples
= codec
->enc_vd
.granulepos
;
772 // granulepos is meaningless for fixed bitrate
775 codec
->encoded_bytes
+= quicktime_position(file
) - offset
;
776 new_encoded_samples
= codec
->encoded_bytes
*
778 (int64_t)samplerate
/
779 (int64_t)codec
->nominal_bitrate
;
781 quicktime_write_chunk_footer(file
,
783 track_map
->current_chunk
,
785 new_encoded_samples
- codec
->encoded_samples
);
786 track_map
->current_chunk
++;
787 codec
->next_chunk_size
= 0;
788 codec
->encoded_samples
= new_encoded_samples
;
797 static int set_parameter(quicktime_t
*file
,
802 quicktime_audio_map_t
*atrack
= &(file
->atracks
[track
]);
803 quicktime_vorbis_codec_t
*codec
= ((quicktime_codec_t
*)atrack
->codec
)->priv
;
806 if(!strcasecmp(key
, "vorbis_vbr"))
807 codec
->use_vbr
= *(int*)value
;
809 if(!strcasecmp(key
, "vorbis_bitrate"))
810 codec
->nominal_bitrate
= *(int*)value
;
812 if(!strcasecmp(key
, "vorbis_max_bitrate"))
813 codec
->max_bitrate
= *(int*)value
;
815 if(!strcasecmp(key
, "vorbis_min_bitrate"))
816 codec
->min_bitrate
= *(int*)value
;
821 static void flush(quicktime_t
*file
, int track
)
823 quicktime_audio_map_t
*track_map
= &(file
->atracks
[track
]);
824 quicktime_vorbis_codec_t
*codec
= ((quicktime_codec_t
*)track_map
->codec
)->priv
;
825 if(codec
->encode_initialized
)
829 int64_t offset
= quicktime_position(file
);
830 long output_position
= codec
->enc_vd
.granulepos
;
831 int chunk_started
= 0;
832 quicktime_trak_t
*trak
= track_map
->track
;
833 int sample_rate
= trak
->mdia
.minf
.stbl
.stsd
.table
[0].sample_rate
;
834 quicktime_atom_t chunk_atom
;
836 vorbis_analysis_wrote(&codec
->enc_vd
,0);
842 int new_encoded_samples
= codec
->enc_vd
.granulepos
;
845 codec
->encoded_bytes
+= quicktime_position(file
) - offset
;
846 new_encoded_samples
= codec
->encoded_bytes
*
848 (int64_t)sample_rate
/
849 (int64_t)codec
->nominal_bitrate
;
851 quicktime_write_chunk_footer(file
,
853 track_map
->current_chunk
,
855 new_encoded_samples
- codec
->encoded_samples
);
856 track_map
->current_chunk
++;
857 codec
->next_chunk_size
= 0;
862 void quicktime_init_codec_vorbis(quicktime_audio_map_t
*atrack
)
864 quicktime_codec_t
*codec_base
= (quicktime_codec_t
*)atrack
->codec
;
865 quicktime_vorbis_codec_t
*codec
;
867 /* Init public items */
868 codec_base
->priv
= calloc(1, sizeof(quicktime_vorbis_codec_t
));
869 codec_base
->delete_acodec
= delete_codec
;
870 codec_base
->decode_audio
= decode
;
871 codec_base
->encode_audio
= encode
;
872 codec_base
->set_parameter
= set_parameter
;
873 codec_base
->flush
= flush
;
874 codec_base
->fourcc
= QUICKTIME_VORBIS
;
875 codec_base
->title
= "OGG Vorbis";
876 codec_base
->desc
= "OGG Vorbis for video. (Not standardized)";
878 codec
= codec_base
->priv
;
879 codec
->nominal_bitrate
= 128000;
880 codec
->max_bitrate
= -1;
881 codec
->min_bitrate
= -1;