1 #include "funcprotos.h"
4 #include "vorbis/vorbisenc.h"
6 // Attempts to read more samples than this will crash
7 #define OUTPUT_ALLOCATION 0x100000
8 #define CLAMP(x, y, z) ((x) = ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x))))
16 int encode_initialized
;
17 ogg_stream_state enc_os
;
21 vorbis_comment enc_vc
;
22 vorbis_dsp_state enc_vd
;
24 // Number of samples written to disk
26 // Number of bytes written to disk
27 int64_t encoded_bytes
;
30 // Number of samples encoded into the chunk
35 ogg_sync_state dec_oy
; /* sync and verify incoming physical bitstream */
36 ogg_stream_state dec_os
; /* take physical pages, weld into a logical
38 ogg_page dec_og
; /* one Ogg bitstream page. Vorbis packets are inside */
39 ogg_packet dec_op
; /* one raw packet of data for decode */
41 vorbis_info dec_vi
; /* struct that stores all the static vorbis bitstream
43 vorbis_comment dec_vc
; /* struct that stores all the bitstream user comments */
44 vorbis_dsp_state dec_vd
; /* central working state for the packet->PCM decoder */
45 vorbis_block dec_vb
; /* local working space for packet->PCM decode */
47 unsigned int dec_current_serialno
;
48 int decode_initialized
;
51 // Number of last sample relative to file
52 int64_t output_position
;
53 // Number of last sample relative to output buffer
55 // Number of samples in output buffer
57 // Number of samples allocated in output buffer
58 long output_allocated
;
59 // Current reading position in file
61 // Number of samples decoded in the current chunk
63 } quicktime_vorbis_codec_t
;
66 /* =================================== public for vorbis */
68 static int delete_codec(quicktime_audio_map_t
*atrack
)
70 quicktime_vorbis_codec_t
*codec
= ((quicktime_codec_t
*)atrack
->codec
)->priv
;
73 if(codec
->encode_initialized
)
75 ogg_stream_clear(&codec
->enc_os
);
76 vorbis_block_clear(&codec
->enc_vb
);
77 vorbis_dsp_clear(&codec
->enc_vd
);
78 vorbis_comment_clear(&codec
->enc_vc
);
79 vorbis_info_clear(&codec
->enc_vi
);
82 if(codec
->decode_initialized
)
86 for(i
= 0; i
< atrack
->channels
; i
++)
87 free(codec
->output
[i
]);
92 ogg_stream_clear(&codec
->dec_os
);
93 vorbis_block_clear(&codec
->dec_vb
);
94 vorbis_dsp_clear(&codec
->dec_vd
);
95 vorbis_comment_clear(&codec
->dec_vc
);
96 vorbis_info_clear(&codec
->dec_vi
);
107 // Buffer fragment should be bigger then largest page header so
108 // all lacing bytes can be decoded.
109 #define BUFFER_FRAGMENT 4096
111 // Calculate chunk length from OggS headers. This is the worst case
112 // but it's better not to assume libogg is going to do anything for us.
114 #define SEGMENT_OFFSET 0x1a
115 #define LACE_OFFSET 0x1b
116 static int chunk_len(quicktime_t
*file
, int64_t offset
, int64_t next_chunk
)
119 unsigned char buffer
[BUFFER_FRAGMENT
];
121 int segment_count
= 0;
122 int segment_size
= 0;
127 while(offset
< next_chunk
)
129 quicktime_set_position(file
, offset
);
130 result
= !quicktime_read_data(file
, buffer
, BUFFER_FRAGMENT
);
137 if(memcmp(buffer
, "OggS", 4))
145 // Decode size of OggS page
146 segment_count
= buffer
[SEGMENT_OFFSET
];
148 // Decode one segment at a time
151 while(segment_count
> 0)
153 page_size
+= buffer
[i
++];
156 accum
+= i
+ page_size
;
157 offset
+= i
+ page_size
;
165 // Calculates the chunk size based on ogg pages.
166 #define READ_CHUNK(chunk) \
168 int64_t offset1 = quicktime_chunk_to_offset(file, trak, (chunk)); \
169 int64_t offset2 = quicktime_chunk_to_offset(file, trak, (chunk) + 1); \
171 if(offset2 == offset1) \
175 size = chunk_len(file, offset1, \
176 offset2 > offset1 ? offset2 : offset1 + 0xfffff); \
178 buffer = ogg_sync_buffer(&codec->dec_oy, size); \
179 quicktime_set_position(file, offset1); \
180 result = !quicktime_read_data(file, buffer, size); \
181 ogg_sync_wrote(&codec->dec_oy, size); \
183 /* printf("READ_CHUNK size=%d\n", size); */ \
184 /* printf("%llx %x: ", quicktime_chunk_to_offset(file, trak, (chunk)), size); */ \
185 /* for(i = 0; i < 16; i++) */ \
186 /* printf("%02x ", buffer[i]); */ \
187 /* printf("result=%d\n", result); */ \
193 static int decode(quicktime_t
*file
,
203 quicktime_audio_map_t
*track_map
= &(file
->atracks
[track
]);
204 quicktime_trak_t
*trak
= track_map
->track
;
205 quicktime_vorbis_codec_t
*codec
= ((quicktime_codec_t
*)track_map
->codec
)->priv
;
206 long current_position
= track_map
->current_position
;
207 long end_position
= current_position
+ samples
;
208 unsigned char *buffer
;
209 // End of data in ogg buffer
217 if(samples
> OUTPUT_ALLOCATION
)
218 printf("vorbis.c decode: can't read more than %p samples at a time.\n", OUTPUT_ALLOCATION
);
222 if(output_i
) bzero(output_i
, sizeof(int16_t) * samples
);
223 if(output_f
) bzero(output_f
, sizeof(float) * samples
);
231 // Seeked outside output buffer's range or not initialized: restart
232 if(current_position
< codec
->output_position
- codec
->output_size
||
233 current_position
> codec
->output_position
||
234 !codec
->decode_initialized
)
237 quicktime_chunk_of_sample(&codec
->output_position
,
241 // We know the first ogg packet in the chunk has a pcm_offset from the encoding.
243 codec
->output_size
= 0;
244 codec
->output_end
= 0;
245 codec
->chunk_samples
= 0;
250 // Initialize and load initial buffer for decoding
251 if(!codec
->decode_initialized
)
254 codec
->decode_initialized
= 1;
256 codec
->output
= malloc(sizeof(float*) * track_map
->channels
);
257 for(i
= 0; i
< track_map
->channels
; i
++)
259 codec
->output
[i
] = malloc(sizeof(float) * OUTPUT_ALLOCATION
);
262 codec
->output_allocated
= OUTPUT_ALLOCATION
;
264 ogg_sync_init(&codec
->dec_oy
); /* Now we can read pages */
269 READ_CHUNK(init_chunk
);
272 if(ogg_sync_pageout(&codec
->dec_oy
, &codec
->dec_og
)!=1)
274 fprintf(stderr
, "decode: ogg_sync_pageout: Must not be Vorbis data\n");
279 ogg_stream_init(&codec
->dec_os
, ogg_page_serialno(&codec
->dec_og
));
280 vorbis_info_init(&codec
->dec_vi
);
281 vorbis_comment_init(&codec
->dec_vc
);
283 if(ogg_stream_pagein(&codec
->dec_os
, &codec
->dec_og
) < 0)
285 fprintf(stderr
,"decode: ogg_stream_pagein: stream version mismatch perhaps.\n");
289 if(ogg_stream_packetout(&codec
->dec_os
, &codec
->dec_op
) != 1)
291 fprintf(stderr
, "decode: ogg_stream_packetout: Must not be Vorbis data\n");
295 if(vorbis_synthesis_headerin(&codec
->dec_vi
, &codec
->dec_vc
, &codec
->dec_op
) < 0)
297 fprintf(stderr
, "decode: vorbis_synthesis_headerin: not a vorbis header\n");
307 result
= ogg_sync_pageout(&codec
->dec_oy
, &codec
->dec_og
);
308 if(result
== 0) break;
312 ogg_stream_pagein(&codec
->dec_os
, &codec
->dec_og
);
316 result
= ogg_stream_packetout(&codec
->dec_os
, &codec
->dec_op
);
318 if(result
== 0) break;
322 fprintf(stderr
, "decode: ogg_stream_packetout: corrupt secondary header\n");
326 vorbis_synthesis_headerin(&codec
->dec_vi
, &codec
->dec_vc
, &codec
->dec_op
);
338 READ_CHUNK(init_chunk
);
342 // Header should never span more than one chunk so assume it's done here
345 vorbis_synthesis_init(&codec
->dec_vd
, &codec
->dec_vi
);
346 vorbis_block_init(&codec
->dec_vd
, &codec
->dec_vb
);
348 // Also the first chunk needed in decoding so don't reread after this.
349 if(codec
->chunk
== init_chunk
- 1)
359 // Don't already have initial chunk from header
362 // Get initial chunk for decoding at new location
364 /* clear out decoding machine state */
365 ogg_stream_clear(&codec
->dec_os
);
366 vorbis_dsp_clear(&codec
->dec_vd
);
367 vorbis_block_clear(&codec
->dec_vb
);
368 ogg_sync_reset(&codec
->dec_oy
);
370 ogg_stream_init(&codec
->dec_os
, ogg_page_serialno(&codec
->dec_og
));
371 ogg_sync_init(&codec
->dec_oy
);
372 vorbis_synthesis_init(&codec
->dec_vd
, &codec
->dec_vi
);
373 vorbis_block_init(&codec
->dec_vd
, &codec
->dec_vb
);
376 READ_CHUNK(codec
->chunk
);
382 // Assume the chunk exists by now and rely on libogg to say if it's out of
396 // Read chunks until output buffer is on or after end_position
398 while(codec
->output_position
< end_position
)
402 // Read chunk to decode if it hasn't been read yet.
405 codec
->chunk_samples
= 0;
407 READ_CHUNK(codec
->chunk
);
415 result
= ogg_sync_pageout(&codec
->dec_oy
, &codec
->dec_og
);
423 // Need more data from chunk
430 // This stage checks for OggS and a checksum error.
431 // It doesn't tell if it's the end of a chunk. Need to manually parse OggS
432 // pages to figure out how big the chunk is.
435 //printf("ogg_sync_pageout=-1\n");
440 ogg_stream_pagein(&codec
->dec_os
, &codec
->dec_og
);
446 //printf("decode 7\n");
447 result
= ogg_stream_packetout(&codec
->dec_os
, &codec
->dec_op
);
449 //printf("decode 8 %d\n", result);
452 //printf("ogg_stream_packetout=0\n");
457 // This stage doesn't check for OggS.
460 //printf("ogg_stream_packetout=-1\n");
472 if(vorbis_synthesis(&codec
->dec_vb
, &codec
->dec_op
) == 0)
474 vorbis_synthesis_blockin(&codec
->dec_vd
,
479 while((result
= vorbis_synthesis_pcmout(&codec
->dec_vd
, &pcm
)) > 0)
481 //printf("vorbis_synthesis_pcmout=%x\n", result);
482 for(i
= 0; i
< track_map
->channels
; i
++)
484 float *output_channel
= codec
->output
[i
];
485 float *input_channel
= pcm
[i
];
486 int k
= codec
->output_end
;
488 for(j
= 0; j
< result
; j
++)
490 output_channel
[k
++] = input_channel
[j
];
491 if(k
>= codec
->output_allocated
)
495 if(i
== track_map
->channels
- 1)
496 codec
->output_end
= k
;
498 //printf("codec->output_end = %d\n", codec->output_end);
500 codec
->output_position
+= result
;
501 codec
->output_size
+= result
;
502 codec
->chunk_samples
+= result
;
503 if(codec
->output_size
> codec
->output_allocated
)
504 codec
->output_size
= codec
->output_allocated
;
505 vorbis_synthesis_read(&codec
->dec_vd
, result
);
508 //printf("decode 11\n");
511 // Reset end of page so it isn't interpreted as an end of chunk
520 //printf("decode 12 got=%x\n", codec->chunk_samples);
527 while(codec
->output_position
< end_position
)
529 for(i
= 0; i
< track_map
->channels
; i
++)
530 codec
->output
[i
][codec
->output_end
] = 0;
533 if(codec
->output_end
>= codec
->output_allocated
)
534 codec
->output_end
= 0;
535 codec
->output_position
++;
537 //printf("decode 15\n");
540 //printf("decode 2 codec->output_position=%lld codec->output_end=%d codec->output_size=%d\n",
541 // codec->output_position, codec->output_end, codec->output_size);
543 current_position
= track_map
->current_position
;
544 i
= codec
->output_end
- (codec
->output_position
- current_position
);
546 while(i
< 0) i
+= codec
->output_allocated
;
547 pcm
= codec
->output
[channel
];
551 for( ; j
< samples
; j
++)
553 int sample
= pcm
[i
] * 32767;
554 CLAMP(sample
, -32768, 32767);
555 output_i
[j
] = sample
;
558 if(i
>= codec
->output_allocated
) i
= 0;
564 for( ; j
< samples
; j
++)
566 output_f
[j
] = pcm
[i
];
568 if(i
>= codec
->output_allocated
) i
= 0;
571 //printf("decode 16\n");
598 int eos = !ogg_stream_flush(&codec->enc_os, &codec->enc_og); \
604 quicktime_write_chunk_header(file, trak, &chunk_atom); \
607 result = !quicktime_write_data(file, codec->enc_og.header, codec->enc_og.header_len); \
608 size += codec->enc_og.header_len; \
612 result = !quicktime_write_data(file, codec->enc_og.body, codec->enc_og.body_len); \
613 size += codec->enc_og.body_len; \
623 while(vorbis_analysis_blockout(&codec->enc_vd, &codec->enc_vb) == 1) \
625 vorbis_analysis(&codec->enc_vb, &codec->enc_op); \
626 vorbis_bitrate_addblock(&codec->enc_vb); \
627 while(vorbis_bitrate_flushpacket(&codec->enc_vd, &codec->enc_op)) \
629 ogg_stream_packetin(&codec->enc_os, &codec->enc_op); \
633 if(!ogg_stream_pageout(&codec->enc_os, &codec->enc_og)) break; \
639 quicktime_write_chunk_header(file, trak, &chunk_atom); \
641 result = !quicktime_write_data(file, codec->enc_og.header, codec->enc_og.header_len); \
642 size += codec->enc_og.header_len; \
646 result = !quicktime_write_data(file, codec->enc_og.body, codec->enc_og.body_len); \
647 size += codec->enc_og.body_len; \
650 if(ogg_page_eos(&codec->enc_og)) break; \
656 static int encode(quicktime_t
*file
,
663 int64_t offset
= quicktime_position(file
);
664 quicktime_audio_map_t
*track_map
= &(file
->atracks
[track
]);
665 quicktime_trak_t
*trak
= track_map
->track
;
666 quicktime_vorbis_codec_t
*codec
= ((quicktime_codec_t
*)track_map
->codec
)->priv
;
667 int samplerate
= trak
->mdia
.minf
.stbl
.stsd
.table
[0].sample_rate
;
670 int chunk_started
= 0;
671 quicktime_atom_t chunk_atom
;
674 if(samplerate
< 32000)
676 printf("encode: sample rate %d not supported.\n", samplerate
);
684 if(!codec
->encode_initialized
)
687 ogg_packet header_comm
;
688 ogg_packet header_code
;
691 codec
->encode_initialized
= 1;
693 trak
->mdia
.minf
.stbl
.stsd
.table
[0].sample_size
= 0;
694 vorbis_info_init(&codec
->enc_vi
);
698 result
= vorbis_encode_setup_managed(&codec
->enc_vi
,
702 codec
->nominal_bitrate
,
704 result
|= vorbis_encode_ctl(&codec
->enc_vi
, OV_ECTL_RATEMANAGE_AVG
, NULL
);
705 result
|= vorbis_encode_setup_init(&codec
->enc_vi
);
709 vorbis_encode_init(&codec
->enc_vi
,
713 codec
->nominal_bitrate
,
718 vorbis_comment_init(&codec
->enc_vc
);
719 vorbis_analysis_init(&codec
->enc_vd
, &codec
->enc_vi
);
720 vorbis_block_init(&codec
->enc_vd
, &codec
->enc_vb
);
722 ogg_stream_init(&codec
->enc_os
, rand());
725 vorbis_analysis_headerout(&codec
->enc_vd
,
731 ogg_stream_packetin(&codec
->enc_os
, &header
);
732 ogg_stream_packetin(&codec
->enc_os
, &header_comm
);
733 ogg_stream_packetin(&codec
->enc_os
, &header_code
);
738 output
= vorbis_analysis_buffer(&codec
->enc_vd
, samples
);
743 for(i
= 0; i
< track_map
->channels
; i
++)
745 for(j
= 0; j
< samples
; j
++)
747 output
[i
][j
] = (float)input_i
[i
][j
] / (float)32768;
755 for(i
= 0; i
< track_map
->channels
; i
++)
757 memcpy(output
[i
], input_f
[i
], sizeof(float) * samples
);
761 vorbis_analysis_wrote(&codec
->enc_vd
, samples
);
765 codec
->next_chunk_size
+= samples
;
770 int new_encoded_samples
= codec
->enc_vd
.granulepos
;
771 // granulepos is meaningless for fixed bitrate
774 codec
->encoded_bytes
+= quicktime_position(file
) - offset
;
775 new_encoded_samples
= codec
->encoded_bytes
*
777 (int64_t)samplerate
/
778 (int64_t)codec
->nominal_bitrate
;
780 quicktime_write_chunk_footer(file
,
782 track_map
->current_chunk
,
784 new_encoded_samples
- codec
->encoded_samples
);
785 track_map
->current_chunk
++;
786 codec
->next_chunk_size
= 0;
787 codec
->encoded_samples
= new_encoded_samples
;
796 static int set_parameter(quicktime_t
*file
,
801 quicktime_audio_map_t
*atrack
= &(file
->atracks
[track
]);
802 quicktime_vorbis_codec_t
*codec
= ((quicktime_codec_t
*)atrack
->codec
)->priv
;
805 if(!strcasecmp(key
, "vorbis_vbr"))
806 codec
->use_vbr
= *(int*)value
;
808 if(!strcasecmp(key
, "vorbis_bitrate"))
809 codec
->nominal_bitrate
= *(int*)value
;
811 if(!strcasecmp(key
, "vorbis_max_bitrate"))
812 codec
->max_bitrate
= *(int*)value
;
814 if(!strcasecmp(key
, "vorbis_min_bitrate"))
815 codec
->min_bitrate
= *(int*)value
;
820 static void flush(quicktime_t
*file
, int track
)
822 quicktime_audio_map_t
*track_map
= &(file
->atracks
[track
]);
823 quicktime_vorbis_codec_t
*codec
= ((quicktime_codec_t
*)track_map
->codec
)->priv
;
824 if(codec
->encode_initialized
)
828 int64_t offset
= quicktime_position(file
);
829 long output_position
= codec
->enc_vd
.granulepos
;
830 int chunk_started
= 0;
831 quicktime_trak_t
*trak
= track_map
->track
;
832 int sample_rate
= trak
->mdia
.minf
.stbl
.stsd
.table
[0].sample_rate
;
833 quicktime_atom_t chunk_atom
;
835 vorbis_analysis_wrote(&codec
->enc_vd
,0);
841 int new_encoded_samples
= codec
->enc_vd
.granulepos
;
844 codec
->encoded_bytes
+= quicktime_position(file
) - offset
;
845 new_encoded_samples
= codec
->encoded_bytes
*
847 (int64_t)sample_rate
/
848 (int64_t)codec
->nominal_bitrate
;
850 quicktime_write_chunk_footer(file
,
852 track_map
->current_chunk
,
854 new_encoded_samples
- codec
->encoded_samples
);
855 track_map
->current_chunk
++;
856 codec
->next_chunk_size
= 0;
861 void quicktime_init_codec_vorbis(quicktime_audio_map_t
*atrack
)
863 quicktime_codec_t
*codec_base
= (quicktime_codec_t
*)atrack
->codec
;
864 quicktime_vorbis_codec_t
*codec
;
866 /* Init public items */
867 codec_base
->priv
= calloc(1, sizeof(quicktime_vorbis_codec_t
));
868 codec_base
->delete_acodec
= delete_codec
;
869 codec_base
->decode_audio
= decode
;
870 codec_base
->encode_audio
= encode
;
871 codec_base
->set_parameter
= set_parameter
;
872 codec_base
->flush
= flush
;
873 codec_base
->fourcc
= QUICKTIME_VORBIS
;
874 codec_base
->title
= "OGG Vorbis";
875 codec_base
->desc
= "OGG Vorbis for video. (Not standardized)";
877 codec
= codec_base
->priv
;
878 codec
->nominal_bitrate
= 128000;
879 codec
->max_bitrate
= -1;
880 codec
->min_bitrate
= -1;