New API wrapper for the encoder.
[xiph/unicode.git] / theora-exp / lib / encinfo.c
blobc5d16888e9004e6131aae9c2555883e243a3f381
1 #include <stdlib.h>
2 #include <string.h>
3 #include "internal.h"
4 #include "enquant.h"
5 #include "huffenc.h"
9 /*Packs a series of octets from a given byte array into the pack buffer.
10 _opb: The pack buffer to store the octets in.
11 _buf: The byte array containing the bytes to pack.
12 _len: The number of octets to pack.*/
13 static void oc_pack_octets(oggpack_buffer *_opb,const char *_buf,int _len){
14 int i;
15 for(i=0;i<_len;i++)oggpackB_write(_opb,*_buf++,8);
20 int oc_state_flushheader(oc_theora_state *_state,int *_packet_state,
21 oggpack_buffer *_opb,const th_quant_info *_qinfo,
22 const th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS],
23 const char *_vendor,th_comment *_tc,ogg_packet *_op){
24 if(_op==NULL)return TH_EFAULT;
25 switch(*_packet_state){
26 /*Codec info header.*/
27 case OC_PACKET_INFO_HDR:{
28 if(_state==NULL)return TH_EFAULT;
29 oggpackB_reset(_opb);
30 /*Mark this packet as the info header.*/
31 oggpackB_write(_opb,0x80,8);
32 /*Write the codec string.*/
33 oc_pack_octets(_opb,"theora",6);
34 /*Write the codec bitstream version.*/
35 oggpackB_write(_opb,TH_VERSION_MAJOR,8);
36 oggpackB_write(_opb,TH_VERSION_MINOR,8);
37 oggpackB_write(_opb,TH_VERSION_SUB,8);
38 /*Describe the encoded frame.*/
39 oggpackB_write(_opb,_state->info.frame_width>>4,16);
40 oggpackB_write(_opb,_state->info.frame_height>>4,16);
41 oggpackB_write(_opb,_state->info.pic_width,24);
42 oggpackB_write(_opb,_state->info.pic_height,24);
43 oggpackB_write(_opb,_state->info.pic_x,8);
44 oggpackB_write(_opb,_state->info.frame_height-
45 _state->info.pic_height-_state->info.pic_y,8);
46 oggpackB_write(_opb,_state->info.fps_numerator,32);
47 oggpackB_write(_opb,_state->info.fps_denominator,32);
48 oggpackB_write(_opb,_state->info.aspect_numerator,24);
49 oggpackB_write(_opb,_state->info.aspect_denominator,24);
50 oggpackB_write(_opb,_state->info.colorspace,8);
51 oggpackB_write(_opb,_state->info.target_bitrate,24);
52 oggpackB_write(_opb,_state->info.quality,6);
53 oggpackB_write(_opb,_state->info.keyframe_granule_shift,5);
54 oggpackB_write(_opb,_state->info.pixel_fmt,2);
55 /*Spare configuration bits.*/
56 oggpackB_write(_opb,0,3);
57 _op->b_o_s=1;
58 }break;
59 /*Comment header.*/
60 case OC_PACKET_COMMENT_HDR:{
61 int vendor_len;
62 int i;
63 if(_tc==NULL)return TH_EFAULT;
64 vendor_len=strlen(_vendor);
65 oggpackB_reset(_opb);
66 /*Mark this packet as the comment header.*/
67 oggpackB_write(_opb,0x81,8);
68 /*Write the codec string.*/
69 oc_pack_octets(_opb,"theora",6);
70 /*Write the vendor string.*/
71 oggpack_write(_opb,vendor_len,32);
72 oc_pack_octets(_opb,_vendor,vendor_len);
73 oggpack_write(_opb,_tc->comments,32);
74 for(i=0;i<_tc->comments;i++){
75 if(_tc->user_comments[i]!=NULL){
76 oggpack_write(_opb,_tc->comment_lengths[i],32);
77 oc_pack_octets(_opb,_tc->user_comments[i],
78 _tc->comment_lengths[i]);
80 else oggpack_write(_opb,0,32);
82 _op->b_o_s=0;
83 }break;
84 /*Codec setup header.*/
85 case OC_PACKET_SETUP_HDR:{
86 int ret;
87 oggpackB_reset(_opb);
88 /*Mark this packet as the setup header.*/
89 oggpackB_write(_opb,0x82,8);
90 /*Write the codec string.*/
91 oc_pack_octets(_opb,"theora",6);
92 /*Write the quantizer tables.*/
93 oc_quant_params_pack(_opb,_qinfo);
94 /*Write the huffman codes.*/
95 ret=oc_huff_codes_pack(_opb,_codes);
96 /*This should never happen, because we validate the tables when they
97 are set.
98 If you see, it's a good chance memory is being corrupted.*/
99 if(ret<0)return ret;
100 _op->b_o_s=0;
101 }break;
102 /*No more headers to emit.*/
103 default:return 0;
105 /*This is kind of fugly: we hand the user a buffer which they do not own.
106 We will overwrite it when the next packet is output, so the user better be
107 done with it by then.
108 Vorbis is little better: it hands back buffers that it will free the next
109 time the headers are requested, or when the encoder is cleared.
110 Hopefully libogg2 will make this much cleaner.*/
111 _op->packet=oggpackB_get_buffer(_opb);
112 _op->bytes=oggpackB_bytes(_opb);
113 _op->e_o_s=0;
114 _op->granulepos=0;
115 /*Is this smart? Vorbis does not even set this field.*/
116 _op->packetno=0;
117 return ++(*_packet_state)+3;