1 #include "funcprotos.h"
6 #include "vorbis/vorbisenc.h"
8 // Attempts to read more samples than this will crash
9 #define OUTPUT_ALLOCATION 0x100000
10 #define CLAMP(x, y, z) ((x) = ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x))))
18 int encode_initialized;
19 ogg_stream_state enc_os;
23 vorbis_comment enc_vc;
24 vorbis_dsp_state enc_vd;
26 // Number of samples written to disk
28 // Number of bytes written to disk
29 int64_t encoded_bytes;
32 // Number of samples encoded into the chunk
37 ogg_sync_state dec_oy; /* sync and verify incoming physical bitstream */
38 ogg_stream_state dec_os; /* take physical pages, weld into a logical
40 ogg_page dec_og; /* one Ogg bitstream page. Vorbis packets are inside */
41 ogg_packet dec_op; /* one raw packet of data for decode */
43 vorbis_info dec_vi; /* struct that stores all the static vorbis bitstream
45 vorbis_comment dec_vc; /* struct that stores all the bitstream user comments */
46 vorbis_dsp_state dec_vd; /* central working state for the packet->PCM decoder */
47 vorbis_block dec_vb; /* local working space for packet->PCM decode */
49 unsigned int dec_current_serialno;
50 int decode_initialized;
53 // Number of last sample relative to file
54 int64_t output_position;
55 // Number of last sample relative to output buffer
57 // Number of samples in output buffer
59 // Number of samples allocated in output buffer
60 long output_allocated;
61 // Current reading position in file
63 // Number of samples decoded in the current chunk
65 } quicktime_vorbis_codec_t;
68 /* =================================== public for vorbis */
70 static void delete_codec(quicktime_audio_map_t *atrack)
72 quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
75 if(codec->encode_initialized)
77 ogg_stream_clear(&codec->enc_os);
78 vorbis_block_clear(&codec->enc_vb);
79 vorbis_dsp_clear(&codec->enc_vd);
80 vorbis_comment_clear(&codec->enc_vc);
81 vorbis_info_clear(&codec->enc_vi);
84 if(codec->decode_initialized)
88 for(i = 0; i < atrack->channels; i++)
89 free(codec->output[i]);
94 ogg_stream_clear(&codec->dec_os);
95 vorbis_block_clear(&codec->dec_vb);
96 vorbis_dsp_clear(&codec->dec_vd);
97 vorbis_comment_clear(&codec->dec_vc);
98 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;
126 while(offset < next_chunk)
128 quicktime_set_position(file, offset);
129 result = !quicktime_read_data(file, (char*)buffer, BUFFER_FRAGMENT);
130 if(result || memcmp(buffer, "OggS", 4))
133 // Decode size of OggS page
134 segment_count = buffer[SEGMENT_OFFSET];
136 // Decode one segment at a time
139 while(segment_count > 0)
141 page_size += buffer[i++];
144 accum += i + page_size;
145 offset += i + page_size;
153 // Calculates the chunk size based on ogg pages.
154 #define READ_CHUNK(chunk) \
156 int64_t offset1 = quicktime_chunk_to_offset(file, trak, (chunk)); \
157 int64_t offset2 = quicktime_chunk_to_offset(file, trak, (chunk) + 1); \
159 if(offset2 == offset1) \
163 size = chunk_len(file, offset1, \
164 offset2 > offset1 ? offset2 : offset1 + 0xfffff); \
166 buffer = (char*)ogg_sync_buffer(&codec->dec_oy, size); \
167 quicktime_set_position(file, offset1); \
168 result = !quicktime_read_data(file, (char*)buffer, size); \
169 ogg_sync_wrote(&codec->dec_oy, size); \
171 /* printf("READ_CHUNK size=%d\n", size); */ \
172 /* printf("%llx %x: ", quicktime_chunk_to_offset(file, trak, (chunk)), size); */ \
173 /* for(i = 0; i < 16; i++) */ \
174 /* printf("%02x ", buffer[i]); */ \
175 /* printf("result=%d\n", result); */ \
181 static int decode(quicktime_t *file,
190 quicktime_audio_map_t *track_map = &(file->atracks[track]);
191 quicktime_trak_t *trak = track_map->track;
192 quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
193 long current_position = track_map->current_position;
194 long end_position = current_position + samples;
196 // End of data in ogg buffer
202 if(samples > OUTPUT_ALLOCATION)
203 printf("vorbis.c decode: can't read more than %d samples at a time.\n", OUTPUT_ALLOCATION);
207 if(output_i) bzero(output_i, sizeof(int16_t) * samples);
208 if(output_f) bzero(output_f, sizeof(float) * samples);
216 // Seeked outside output buffer's range or not initialized: restart
217 if(current_position < codec->output_position - codec->output_size ||
218 current_position > codec->output_position ||
219 !codec->decode_initialized)
222 quicktime_chunk_of_sample(&codec->output_position,
226 // We know the first ogg packet in the chunk has a pcm_offset from the encoding.
228 codec->output_size = 0;
229 codec->output_end = 0;
230 codec->chunk_samples = 0;
235 // Initialize and load initial buffer for decoding
236 if(!codec->decode_initialized)
239 codec->decode_initialized = 1;
241 codec->output = malloc(sizeof(float*) * track_map->channels);
242 for(i = 0; i < track_map->channels; i++)
244 codec->output[i] = malloc(sizeof(float) * OUTPUT_ALLOCATION);
247 codec->output_allocated = OUTPUT_ALLOCATION;
249 ogg_sync_init(&codec->dec_oy); /* Now we can read pages */
254 READ_CHUNK(init_chunk);
257 if(ogg_sync_pageout(&codec->dec_oy, &codec->dec_og)!=1)
259 fprintf(stderr, "decode: ogg_sync_pageout: Must not be Vorbis data\n");
264 ogg_stream_init(&codec->dec_os, ogg_page_serialno(&codec->dec_og));
265 vorbis_info_init(&codec->dec_vi);
266 vorbis_comment_init(&codec->dec_vc);
268 if(ogg_stream_pagein(&codec->dec_os, &codec->dec_og) < 0)
270 fprintf(stderr,"decode: ogg_stream_pagein: stream version mismatch perhaps.\n");
274 if(ogg_stream_packetout(&codec->dec_os, &codec->dec_op) != 1)
276 fprintf(stderr, "decode: ogg_stream_packetout: Must not be Vorbis data\n");
280 if(vorbis_synthesis_headerin(&codec->dec_vi, &codec->dec_vc, &codec->dec_op) < 0)
282 fprintf(stderr, "decode: vorbis_synthesis_headerin: not a vorbis header\n");
292 result = ogg_sync_pageout(&codec->dec_oy, &codec->dec_og);
293 if(result == 0) break;
297 ogg_stream_pagein(&codec->dec_os, &codec->dec_og);
301 result = ogg_stream_packetout(&codec->dec_os, &codec->dec_op);
303 if(result == 0) break;
307 fprintf(stderr, "decode: ogg_stream_packetout: corrupt secondary header\n");
311 vorbis_synthesis_headerin(&codec->dec_vi, &codec->dec_vc, &codec->dec_op);
323 READ_CHUNK(init_chunk);
327 // Header should never span more than one chunk so assume it's done here
330 vorbis_synthesis_init(&codec->dec_vd, &codec->dec_vi);
331 vorbis_block_init(&codec->dec_vd, &codec->dec_vb);
333 // Also the first chunk needed in decoding so don't reread after this.
334 if(codec->chunk == init_chunk - 1)
344 // Don't already have initial chunk from header
347 // Get initial chunk for decoding at new location
349 /* clear out decoding machine state */
350 ogg_stream_clear(&codec->dec_os);
351 vorbis_dsp_clear(&codec->dec_vd);
352 vorbis_block_clear(&codec->dec_vb);
353 ogg_sync_reset(&codec->dec_oy);
355 ogg_stream_init(&codec->dec_os, ogg_page_serialno(&codec->dec_og));
356 ogg_sync_init(&codec->dec_oy);
357 vorbis_synthesis_init(&codec->dec_vd, &codec->dec_vi);
358 vorbis_block_init(&codec->dec_vd, &codec->dec_vb);
361 READ_CHUNK(codec->chunk);
367 // Assume the chunk exists by now and rely on libogg to say if it's out of
381 // Read chunks until output buffer is on or after end_position
383 while(codec->output_position < end_position)
387 // Read chunk to decode if it hasn't been read yet.
390 codec->chunk_samples = 0;
392 READ_CHUNK(codec->chunk);
400 result = ogg_sync_pageout(&codec->dec_oy, &codec->dec_og);
408 // Need more data from chunk
415 // This stage checks for OggS and a checksum error.
416 // It doesn't tell if it's the end of a chunk. Need to manually parse OggS
417 // pages to figure out how big the chunk is.
420 //printf("ogg_sync_pageout=-1\n");
425 ogg_stream_pagein(&codec->dec_os, &codec->dec_og);
431 //printf("decode 7\n");
432 result = ogg_stream_packetout(&codec->dec_os, &codec->dec_op);
434 //printf("decode 8 %d\n", result);
437 //printf("ogg_stream_packetout=0\n");
442 // This stage doesn't check for OggS.
445 //printf("ogg_stream_packetout=-1\n");
457 if(vorbis_synthesis(&codec->dec_vb, &codec->dec_op) == 0)
459 vorbis_synthesis_blockin(&codec->dec_vd,
464 while((result = vorbis_synthesis_pcmout(&codec->dec_vd, &pcm)) > 0)
466 //printf("vorbis_synthesis_pcmout=%x\n", result);
467 for(i = 0; i < track_map->channels; i++)
469 float *output_channel = codec->output[i];
470 float *input_channel = pcm[i];
471 int k = codec->output_end;
473 for(j = 0; j < result; j++)
475 output_channel[k++] = input_channel[j];
476 if(k >= codec->output_allocated)
480 if(i == track_map->channels - 1)
481 codec->output_end = k;
483 //printf("codec->output_end = %d\n", codec->output_end);
485 codec->output_position += result;
486 codec->output_size += result;
487 codec->chunk_samples += result;
488 if(codec->output_size > codec->output_allocated)
489 codec->output_size = codec->output_allocated;
490 vorbis_synthesis_read(&codec->dec_vd, result);
493 //printf("decode 11\n");
496 // Reset end of page so it isn't interpreted as an end of chunk
505 //printf("decode 12 got=%x\n", codec->chunk_samples);
512 while(codec->output_position < end_position)
514 for(i = 0; i < track_map->channels; i++)
515 codec->output[i][codec->output_end] = 0;
518 if(codec->output_end >= codec->output_allocated)
519 codec->output_end = 0;
520 codec->output_position++;
522 //printf("decode 15\n");
525 //printf("decode 2 codec->output_position=%lld codec->output_end=%d codec->output_size=%d\n",
526 // codec->output_position, codec->output_end, codec->output_size);
528 current_position = track_map->current_position;
529 i = codec->output_end - (codec->output_position - current_position);
531 while(i < 0) i += codec->output_allocated;
532 pcm = codec->output[channel];
536 for( ; j < samples; j++)
538 int sample = pcm[i] * 32767;
539 CLAMP(sample, -32768, 32767);
540 output_i[j] = sample;
543 if(i >= codec->output_allocated) i = 0;
549 for( ; j < samples; j++)
551 output_f[j] = pcm[i];
553 if(i >= codec->output_allocated) i = 0;
556 //printf("decode 16\n");
583 int eos = !ogg_stream_flush(&codec->enc_os, &codec->enc_og); \
589 quicktime_write_chunk_header(file, trak, &chunk_atom); \
592 result = !quicktime_write_data(file,(char*)codec->enc_og.header, codec->enc_og.header_len); \
593 size += codec->enc_og.header_len; \
597 result = !quicktime_write_data(file,(char*)codec->enc_og.body, codec->enc_og.body_len); \
598 size += codec->enc_og.body_len; \
608 while(vorbis_analysis_blockout(&codec->enc_vd, &codec->enc_vb) == 1) \
610 vorbis_analysis(&codec->enc_vb, &codec->enc_op); \
611 vorbis_bitrate_addblock(&codec->enc_vb); \
612 while(vorbis_bitrate_flushpacket(&codec->enc_vd, &codec->enc_op)) \
614 ogg_stream_packetin(&codec->enc_os, &codec->enc_op); \
618 if(!ogg_stream_pageout(&codec->enc_os, &codec->enc_og)) break; \
624 quicktime_write_chunk_header(file, trak, &chunk_atom); \
626 result = !quicktime_write_data(file, (char*)codec->enc_og.header, codec->enc_og.header_len); \
627 size += codec->enc_og.header_len; \
631 result = !quicktime_write_data(file, (char*)codec->enc_og.body, codec->enc_og.body_len); \
632 size += codec->enc_og.body_len; \
635 if(ogg_page_eos(&codec->enc_og)) break; \
641 static int encode(quicktime_t *file,
648 int64_t offset = quicktime_position(file);
649 quicktime_audio_map_t *track_map = &(file->atracks[track]);
650 quicktime_trak_t *trak = track_map->track;
651 quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
652 int samplerate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
655 int chunk_started = 0;
656 quicktime_atom_t chunk_atom;
659 if(samplerate < 32000)
661 printf("encode: sample rate %d not supported.\n", samplerate);
669 if(!codec->encode_initialized)
672 ogg_packet header_comm;
673 ogg_packet header_code;
676 codec->encode_initialized = 1;
678 trak->mdia.minf.stbl.stsd.table[0].sample_size = 0;
679 vorbis_info_init(&codec->enc_vi);
683 result = vorbis_encode_setup_managed(&codec->enc_vi,
687 codec->nominal_bitrate,
689 result |= vorbis_encode_ctl(&codec->enc_vi, OV_ECTL_RATEMANAGE_AVG, NULL);
690 result |= vorbis_encode_setup_init(&codec->enc_vi);
694 vorbis_encode_init(&codec->enc_vi,
698 codec->nominal_bitrate,
703 vorbis_comment_init(&codec->enc_vc);
704 vorbis_analysis_init(&codec->enc_vd, &codec->enc_vi);
705 vorbis_block_init(&codec->enc_vd, &codec->enc_vb);
707 ogg_stream_init(&codec->enc_os, rand());
710 vorbis_analysis_headerout(&codec->enc_vd,
716 ogg_stream_packetin(&codec->enc_os, &header);
717 ogg_stream_packetin(&codec->enc_os, &header_comm);
718 ogg_stream_packetin(&codec->enc_os, &header_code);
723 output = vorbis_analysis_buffer(&codec->enc_vd, samples);
728 for(i = 0; i < track_map->channels; i++)
730 for(j = 0; j < samples; j++)
732 output[i][j] = (float)input_i[i][j] / (float)32768;
740 for(i = 0; i < track_map->channels; i++)
742 memcpy(output[i], input_f[i], sizeof(float) * samples);
746 vorbis_analysis_wrote(&codec->enc_vd, samples);
750 codec->next_chunk_size += samples;
755 int new_encoded_samples = codec->enc_vd.granulepos;
756 // granulepos is meaningless for fixed bitrate
759 codec->encoded_bytes += quicktime_position(file) - offset;
760 new_encoded_samples = codec->encoded_bytes *
762 (int64_t)samplerate /
763 (int64_t)codec->nominal_bitrate;
765 quicktime_write_chunk_footer(file,
767 track_map->current_chunk,
769 new_encoded_samples - codec->encoded_samples);
770 track_map->current_chunk++;
771 codec->next_chunk_size = 0;
772 codec->encoded_samples = new_encoded_samples;
781 static int set_parameter(quicktime_t *file,
786 quicktime_audio_map_t *atrack = &(file->atracks[track]);
787 quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
790 if(!strcasecmp(key, "vorbis_vbr"))
791 codec->use_vbr = *(int*)value;
793 if(!strcasecmp(key, "vorbis_bitrate"))
794 codec->nominal_bitrate = *(int*)value;
796 if(!strcasecmp(key, "vorbis_max_bitrate"))
797 codec->max_bitrate = *(int*)value;
799 if(!strcasecmp(key, "vorbis_min_bitrate"))
800 codec->min_bitrate = *(int*)value;
805 static void flush(quicktime_t *file, int track)
807 quicktime_audio_map_t *track_map = &(file->atracks[track]);
808 quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
809 if(codec->encode_initialized)
813 int64_t offset = quicktime_position(file);
814 //long output_position = codec->enc_vd.granulepos;
815 int chunk_started = 0;
816 quicktime_trak_t *trak = track_map->track;
817 int sample_rate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
818 quicktime_atom_t chunk_atom;
820 vorbis_analysis_wrote(&codec->enc_vd,0);
826 int new_encoded_samples = codec->enc_vd.granulepos;
829 codec->encoded_bytes += quicktime_position(file) - offset;
830 new_encoded_samples = codec->encoded_bytes *
832 (int64_t)sample_rate /
833 (int64_t)codec->nominal_bitrate;
835 quicktime_write_chunk_footer(file,
837 track_map->current_chunk,
839 new_encoded_samples - codec->encoded_samples);
840 track_map->current_chunk++;
841 codec->next_chunk_size = 0;
846 void quicktime_init_codec_vorbis(quicktime_audio_map_t *atrack)
848 quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
849 quicktime_vorbis_codec_t *codec;
851 /* Init public items */
852 codec_base->priv = calloc(1, sizeof(quicktime_vorbis_codec_t));
853 codec_base->delete_acodec = delete_codec;
854 codec_base->decode_audio = decode;
855 codec_base->encode_audio = encode;
856 codec_base->set_parameter = set_parameter;
857 codec_base->flush = flush;
858 codec_base->fourcc = QUICKTIME_VORBIS;
859 codec_base->title = "OGG Vorbis";
860 codec_base->desc = "OGG Vorbis for video. (Not standardized)";
862 codec = codec_base->priv;
863 codec->nominal_bitrate = 128000;
864 codec->max_bitrate = -1;
865 codec->min_bitrate = -1;