summaryrefslogtreecommitdiff
path: root/thirdparty/libtheora/encinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/libtheora/encinfo.c')
-rw-r--r--thirdparty/libtheora/encinfo.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/thirdparty/libtheora/encinfo.c b/thirdparty/libtheora/encinfo.c
new file mode 100644
index 0000000000..83be1dae72
--- /dev/null
+++ b/thirdparty/libtheora/encinfo.c
@@ -0,0 +1,121 @@
+#include <stdlib.h>
+#include <string.h>
+#include "internal.h"
+#include "enquant.h"
+#include "huffenc.h"
+
+
+
+/*Packs a series of octets from a given byte array into the pack buffer.
+ _opb: The pack buffer to store the octets in.
+ _buf: The byte array containing the bytes to pack.
+ _len: The number of octets to pack.*/
+static void oc_pack_octets(oggpack_buffer *_opb,const char *_buf,int _len){
+ int i;
+ for(i=0;i<_len;i++)oggpackB_write(_opb,_buf[i],8);
+}
+
+
+
+int oc_state_flushheader(oc_theora_state *_state,int *_packet_state,
+ oggpack_buffer *_opb,const th_quant_info *_qinfo,
+ const th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS],
+ const char *_vendor,th_comment *_tc,ogg_packet *_op){
+ unsigned char *packet;
+ int b_o_s;
+ if(_op==NULL)return TH_EFAULT;
+ switch(*_packet_state){
+ /*Codec info header.*/
+ case OC_PACKET_INFO_HDR:{
+ if(_state==NULL)return TH_EFAULT;
+ oggpackB_reset(_opb);
+ /*Mark this packet as the info header.*/
+ oggpackB_write(_opb,0x80,8);
+ /*Write the codec string.*/
+ oc_pack_octets(_opb,"theora",6);
+ /*Write the codec bitstream version.*/
+ oggpackB_write(_opb,TH_VERSION_MAJOR,8);
+ oggpackB_write(_opb,TH_VERSION_MINOR,8);
+ oggpackB_write(_opb,TH_VERSION_SUB,8);
+ /*Describe the encoded frame.*/
+ oggpackB_write(_opb,_state->info.frame_width>>4,16);
+ oggpackB_write(_opb,_state->info.frame_height>>4,16);
+ oggpackB_write(_opb,_state->info.pic_width,24);
+ oggpackB_write(_opb,_state->info.pic_height,24);
+ oggpackB_write(_opb,_state->info.pic_x,8);
+ oggpackB_write(_opb,_state->info.pic_y,8);
+ oggpackB_write(_opb,_state->info.fps_numerator,32);
+ oggpackB_write(_opb,_state->info.fps_denominator,32);
+ oggpackB_write(_opb,_state->info.aspect_numerator,24);
+ oggpackB_write(_opb,_state->info.aspect_denominator,24);
+ oggpackB_write(_opb,_state->info.colorspace,8);
+ oggpackB_write(_opb,_state->info.target_bitrate,24);
+ oggpackB_write(_opb,_state->info.quality,6);
+ oggpackB_write(_opb,_state->info.keyframe_granule_shift,5);
+ oggpackB_write(_opb,_state->info.pixel_fmt,2);
+ /*Spare configuration bits.*/
+ oggpackB_write(_opb,0,3);
+ b_o_s=1;
+ }break;
+ /*Comment header.*/
+ case OC_PACKET_COMMENT_HDR:{
+ int vendor_len;
+ int i;
+ if(_tc==NULL)return TH_EFAULT;
+ vendor_len=strlen(_vendor);
+ oggpackB_reset(_opb);
+ /*Mark this packet as the comment header.*/
+ oggpackB_write(_opb,0x81,8);
+ /*Write the codec string.*/
+ oc_pack_octets(_opb,"theora",6);
+ /*Write the vendor string.*/
+ oggpack_write(_opb,vendor_len,32);
+ oc_pack_octets(_opb,_vendor,vendor_len);
+ oggpack_write(_opb,_tc->comments,32);
+ for(i=0;i<_tc->comments;i++){
+ if(_tc->user_comments[i]!=NULL){
+ oggpack_write(_opb,_tc->comment_lengths[i],32);
+ oc_pack_octets(_opb,_tc->user_comments[i],_tc->comment_lengths[i]);
+ }
+ else oggpack_write(_opb,0,32);
+ }
+ b_o_s=0;
+ }break;
+ /*Codec setup header.*/
+ case OC_PACKET_SETUP_HDR:{
+ int ret;
+ oggpackB_reset(_opb);
+ /*Mark this packet as the setup header.*/
+ oggpackB_write(_opb,0x82,8);
+ /*Write the codec string.*/
+ oc_pack_octets(_opb,"theora",6);
+ /*Write the quantizer tables.*/
+ oc_quant_params_pack(_opb,_qinfo);
+ /*Write the huffman codes.*/
+ ret=oc_huff_codes_pack(_opb,_codes);
+ /*This should never happen, because we validate the tables when they
+ are set.
+ If you see, it's a good chance memory is being corrupted.*/
+ if(ret<0)return ret;
+ b_o_s=0;
+ }break;
+ /*No more headers to emit.*/
+ default:return 0;
+ }
+ /*This is kind of fugly: we hand the user a buffer which they do not own.
+ We will overwrite it when the next packet is output, so the user better be
+ done with it by then.
+ Vorbis is little better: it hands back buffers that it will free the next
+ time the headers are requested, or when the encoder is cleared.
+ Hopefully libogg2 will make this much cleaner.*/
+ packet=oggpackB_get_buffer(_opb);
+ /*If there's no packet, malloc failed while writing.*/
+ if(packet==NULL)return TH_EFAULT;
+ _op->packet=packet;
+ _op->bytes=oggpackB_bytes(_opb);
+ _op->b_o_s=b_o_s;
+ _op->e_o_s=0;
+ _op->granulepos=0;
+ _op->packetno=*_packet_state+3;
+ return ++(*_packet_state)+3;
+}