#include #include #include #include #include #include #include extern const char *__progname; static unsigned char frame[640*480*2]; static unsigned char planar_y[640*480]; static unsigned char planar_cb[320*480]; static unsigned char planar_cr[320*480]; static void planarize(void) { unsigned char *ip; unsigned char *op_y; unsigned char *op_cb; unsigned char *op_cr; int y; int x; ip = &frame[0]; op_y = &planar_y[0]; op_cb = &planar_cb[0]; op_cr = &planar_cr[0]; for (y=480;y>0;y--) { for (x=640;x>0;x-=2) { *op_y++ = ip[0]; *op_y++ = ip[2]; *op_cb++ = ip[1]; *op_cr++ = ip[3]; ip += 4; } } } static int rd(void *data, int len) { int r; unsigned char *dp; int l; dp = data; l = len; while (l > 0) { r = read(0,dp,l); if (r < 0) { fprintf(stderr,"%s: input read: %s\n",__progname,strerror(errno)); exit(1); } if (r == 0) return(0); if (r > l) abort(); dp += r; l -= r; } return(1); } static void print_pkt(const ogg_packet *p) { #if 0 int i; fprintf(stderr,"packet: bytes %ld bos %ld eos %ld gpos %lld pno %lld\n", (long int)p->bytes, (long int)p->b_o_s, (long int)p->e_o_s, (long long int)p->granulepos, (long long int)p->packetno ); fprintf(stderr,"packet data:"); for (i=0;ibytes;i++) fprintf(stderr," %02x",p->packet[i]); fprintf(stderr,"\n"); #endif printf("%ld %ld %ld %lld %lld\n", (long int)p->bytes, (long int)p->b_o_s, (long int)p->e_o_s, (long long int)p->granulepos, (long long int)p->packetno ); fwrite(p->packet,1,p->bytes,stdout); } int main(void) { th_info thi; th_enc_ctx *thec; th_comment comm; ogg_packet pkt; th_ycbcr_buffer ibuf; int e; void load_ibuf(void) { ibuf[0].width = 640; ibuf[0].height = 480; ibuf[0].stride = 640; ibuf[0].data = &planar_y[0]; ibuf[1].width = 320; ibuf[1].height = 480; ibuf[1].stride = 320; ibuf[1].data = &planar_cb[0]; ibuf[2].width = 320; ibuf[2].height = 480; ibuf[2].stride = 320; ibuf[2].data = &planar_cr[0]; } void send_ibuf(void) { int e; /* XXX th_ycbcr_buffer is an array (!), hence no & */ e = th_encode_ycbcr_in(thec,ibuf); if (e != 0) { fprintf(stderr,"th_encode_ycbcr_in error %d\n",e); exit(1); } } void drain_output(void) { int e; while (1) { e = th_encode_packetout(thec,0,&pkt); if (e == 0) break; if (e > 0) { print_pkt(&pkt); } else { fprintf(stderr,"th_encode_packetout error %d\n",e); exit(1); } } fflush(0); } thi.version_major = 1; // XXX undocumented thi.version_minor = 1; // XXX undocumented thi.version_subminor = 1; // XXX undocumented thi.frame_width = 640; thi.frame_height = 480; thi.pic_width = 640; thi.pic_height = 480; thi.pic_x = 0; thi.pic_y = 0; /* * The documentation says of these "If either is 0, the frame rate is * undefined.". What it doesn't say is that the encoder will happily * accept such settings, encode them in the resulting stream, and the * decoder will then barf with TH_EBADHEADER. */ thi.fps_numerator = 10; thi.fps_denominator = 1; thi.aspect_numerator = 1; thi.aspect_denominator = 1; thi.colorspace = TH_CS_ITU_REC_470M; thi.pixel_fmt = TH_PF_422; thi.target_bitrate = 0; thi.quality = 0; thi.keyframe_granule_shift = 6; thec = th_encode_alloc(&thi); // th_encode_ctl(...) none needed comm.user_comments = 0; comm.comment_lengths = 0; comm.comments = 0; comm.vendor = 0; while (1) { e = th_encode_flushheader(thec,&comm,&pkt); if (e == 0) break; if (e > 0) { print_pkt(&pkt); } else { fprintf(stderr,"th_encode_flushheader error %d\n",e); exit(1); } } if (! rd(&frame[0],640*480*2)) exit(0); planarize(); while (rd(&frame[0],640*480*2)) { fprintf(stderr,"frame in\n"); load_ibuf(); send_ibuf(); drain_output(); planarize(); } fprintf(stderr,"final frame in\n"); load_ibuf(); send_ibuf(); drain_output(); th_encode_free(thec); printf("."); return(0); }