mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-30 21:21:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			121 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include "state.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;
 | |
| }
 | 
