#include <stdlib.h>
#include <string.h>
#include <ogg/ogg.h>
#include "decint.h"
#if defined(OC_DUMP_IMAGES)
# include <stdio.h>
# include "png.h"
#endif
#if defined(HAVE_CAIRO)
# include <cairo.h>
#endif
#define OC_PP_LEVEL_DISABLED …
#define OC_PP_LEVEL_TRACKDCQI …
#define OC_PP_LEVEL_DEBLOCKY …
#define OC_PP_LEVEL_DERINGY …
#define OC_PP_LEVEL_SDERINGY …
#define OC_PP_LEVEL_DEBLOCKC …
#define OC_PP_LEVEL_DERINGC …
#define OC_PP_LEVEL_SDERINGC …
#define OC_PP_LEVEL_MAX …
static const unsigned char OC_MODE_ALPHABETS[7][OC_NMODES]= …;
static const unsigned char OC_INTERNAL_DCT_TOKEN_EXTRA_BITS[15]= …;
#define OC_DCT_TOKEN_NEEDS_MORE(token) …
#define OC_DCT_TOKEN_FAT_EOB …
#define OC_DCT_EOB_FINISH …
#define OC_DCT_CW_RLEN_SHIFT …
#define OC_DCT_CW_EOB_SHIFT …
#define OC_DCT_CW_FLIP_BIT …
#define OC_DCT_CW_MAG_SHIFT …
#define OC_DCT_CW_PACK(_eobs,_rlen,_mag,_flip) …
#define OC_DCT_CW_FINISH …
#define OC_DCT_TOKEN_EB_POS(_token) …
static const ogg_int32_t OC_DCT_CODE_WORD[92]= …;
static int oc_sb_run_unpack(oc_pack_buf *_opb){ … }
static int oc_block_run_unpack(oc_pack_buf *_opb){ … }
void oc_dec_accel_init_c(oc_dec_ctx *_dec){ … }
static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info,
const th_setup_info *_setup){ … }
static void oc_dec_clear(oc_dec_ctx *_dec){ … }
static int oc_dec_frame_header_unpack(oc_dec_ctx *_dec){ … }
static void oc_dec_mark_all_intra(oc_dec_ctx *_dec){ … }
static unsigned oc_dec_partial_sb_flags_unpack(oc_dec_ctx *_dec){ … }
static void oc_dec_coded_sb_flags_unpack(oc_dec_ctx *_dec){ … }
static void oc_dec_coded_flags_unpack(oc_dec_ctx *_dec){ … }
static const ogg_int16_t OC_VLC_MODE_TREE[26]= …;
static const ogg_int16_t OC_CLC_MODE_TREE[9]= …;
static void oc_dec_mb_modes_unpack(oc_dec_ctx *_dec){ … }
static const ogg_int16_t OC_VLC_MV_COMP_TREE[101]= …;
static const ogg_int16_t OC_CLC_MV_COMP_TREE[65]= …;
static oc_mv oc_mv_unpack(oc_pack_buf *_opb,const ogg_int16_t *_tree){ … }
static void oc_dec_mv_unpack_and_frag_modes_fill(oc_dec_ctx *_dec){ … }
static void oc_dec_block_qis_unpack(oc_dec_ctx *_dec){ … }
static ptrdiff_t oc_dec_dc_coeff_unpack(oc_dec_ctx *_dec,int _huff_idxs[2],
ptrdiff_t _ntoks_left[3][64]){ … }
static int oc_dec_ac_coeff_unpack(oc_dec_ctx *_dec,int _zzi,int _huff_idxs[2],
ptrdiff_t _ntoks_left[3][64],ptrdiff_t _eobs){ … }
static void oc_dec_residual_tokens_unpack(oc_dec_ctx *_dec){ … }
static int oc_dec_postprocess_init(oc_dec_ctx *_dec){ … }
static void oc_dec_pipeline_init(oc_dec_ctx *_dec,
oc_dec_pipeline_state *_pipe){ … }
void oc_dec_dc_unpredict_mcu_plane_c(oc_dec_ctx *_dec,
oc_dec_pipeline_state *_pipe,int _pli){ … }
static void oc_dec_frags_recon_mcu_plane(oc_dec_ctx *_dec,
oc_dec_pipeline_state *_pipe,int _pli){ … }
static void oc_filter_hedge(unsigned char *_dst,int _dst_ystride,
const unsigned char *_src,int _src_ystride,int _qstep,int _flimit,
int *_variance0,int *_variance1){ … }
static void oc_filter_vedge(unsigned char *_dst,int _dst_ystride,
int _qstep,int _flimit,int *_variances){ … }
static void oc_dec_deblock_frag_rows(oc_dec_ctx *_dec,
th_img_plane *_dst,th_img_plane *_src,int _pli,int _fragy0,
int _fragy_end){ … }
static void oc_dering_block(unsigned char *_idata,int _ystride,int _b,
int _dc_scale,int _sharp_mod,int _strong){ … }
#define OC_DERING_THRESH1 …
#define OC_DERING_THRESH2 …
#define OC_DERING_THRESH3 …
#define OC_DERING_THRESH4 …
static void oc_dec_dering_frag_rows(oc_dec_ctx *_dec,th_img_plane *_img,
int _pli,int _fragy0,int _fragy_end){ … }
th_dec_ctx *th_decode_alloc(const th_info *_info,const th_setup_info *_setup){ … }
void th_decode_free(th_dec_ctx *_dec){ … }
int th_decode_ctl(th_dec_ctx *_dec,int _req,void *_buf,
size_t _buf_sz){ … }
static void oc_dec_init_dummy_frame(th_dec_ctx *_dec){ … }
#if defined(HAVE_CAIRO)
static void oc_render_telemetry(th_dec_ctx *_dec,th_ycbcr_buffer _ycbcr,
int _telemetry){
cairo_surface_t *cs;
unsigned char *data;
unsigned char *y_row;
unsigned char *u_row;
unsigned char *v_row;
unsigned char *rgb_row;
int cstride;
int w;
int h;
int x;
int y;
int hdec;
int vdec;
w=_ycbcr[0].width;
h=_ycbcr[0].height;
hdec=!(_dec->state.info.pixel_fmt&1);
vdec=!(_dec->state.info.pixel_fmt&2);
if(_dec->telemetry_frame_data==NULL){
_dec->telemetry_frame_data=_ogg_malloc(
(w*h+2*(w>>hdec)*(h>>vdec))*sizeof(*_dec->telemetry_frame_data));
if(_dec->telemetry_frame_data==NULL)return;
}
cs=cairo_image_surface_create(CAIRO_FORMAT_RGB24,w,h);
data=cairo_image_surface_get_data(cs);
if(data==NULL){
cairo_surface_destroy(cs);
return;
}
cstride=cairo_image_surface_get_stride(cs);
y_row=_ycbcr[0].data;
u_row=_ycbcr[1].data;
v_row=_ycbcr[2].data;
rgb_row=data;
for(y=0;y<h;y++){
for(x=0;x<w;x++){
int r;
int g;
int b;
r=(1904000*y_row[x]+2609823*v_row[x>>hdec]-363703744)/1635200;
g=(3827562*y_row[x]-1287801*u_row[x>>hdec]
-2672387*v_row[x>>hdec]+447306710)/3287200;
b=(952000*y_row[x]+1649289*u_row[x>>hdec]-225932192)/817600;
rgb_row[4*x+0]=OC_CLAMP255(b);
rgb_row[4*x+1]=OC_CLAMP255(g);
rgb_row[4*x+2]=OC_CLAMP255(r);
}
y_row+=_ycbcr[0].stride;
u_row+=_ycbcr[1].stride&-((y&1)|!vdec);
v_row+=_ycbcr[2].stride&-((y&1)|!vdec);
rgb_row+=cstride;
}
{
cairo_t *c;
const oc_fragment *frags;
oc_mv *frag_mvs;
const signed char *mb_modes;
oc_mb_map *mb_maps;
size_t nmbs;
size_t mbi;
int row2;
int col2;
int qim[3]={0,0,0};
if(_dec->state.nqis==2){
int bqi;
bqi=_dec->state.qis[0];
if(_dec->state.qis[1]>bqi)qim[1]=1;
if(_dec->state.qis[1]<bqi)qim[1]=-1;
}
if(_dec->state.nqis==3){
int bqi;
int cqi;
int dqi;
bqi=_dec->state.qis[0];
cqi=_dec->state.qis[1];
dqi=_dec->state.qis[2];
if(cqi>bqi&&dqi>bqi){
if(dqi>cqi){
qim[1]=1;
qim[2]=2;
}
else{
qim[1]=2;
qim[2]=1;
}
}
else if(cqi<bqi&&dqi<bqi){
if(dqi<cqi){
qim[1]=-1;
qim[2]=-2;
}
else{
qim[1]=-2;
qim[2]=-1;
}
}
else{
if(cqi<bqi)qim[1]=-1;
else qim[1]=1;
if(dqi<bqi)qim[2]=-1;
else qim[2]=1;
}
}
c=cairo_create(cs);
frags=_dec->state.frags;
frag_mvs=_dec->state.frag_mvs;
mb_modes=_dec->state.mb_modes;
mb_maps=_dec->state.mb_maps;
nmbs=_dec->state.nmbs;
row2=0;
col2=0;
for(mbi=0;mbi<nmbs;mbi++){
float x;
float y;
int bi;
y=h-(row2+((col2+1>>1)&1))*16-16;
x=(col2>>1)*16;
cairo_set_line_width(c,1.);
if(_dec->state.frame_type==OC_INTRA_FRAME){
if(_dec->telemetry_mbmode&0x02){
cairo_set_source_rgba(c,1.,0,0,.5);
cairo_rectangle(c,x+2.5,y+2.5,11,11);
cairo_stroke_preserve(c);
cairo_set_source_rgba(c,1.,0,0,.25);
cairo_fill(c);
}
}
else{
ptrdiff_t fragi;
int frag_mvx;
int frag_mvy;
for(bi=0;bi<4;bi++){
fragi=mb_maps[mbi][0][bi];
if(fragi>=0&&frags[fragi].coded){
frag_mvx=OC_MV_X(frag_mvs[fragi]);
frag_mvy=OC_MV_Y(frag_mvs[fragi]);
break;
}
}
if(bi<4){
switch(mb_modes[mbi]){
case OC_MODE_INTRA:{
if(_dec->telemetry_mbmode&0x02){
cairo_set_source_rgba(c,1.,0,0,.5);
cairo_rectangle(c,x+2.5,y+2.5,11,11);
cairo_stroke_preserve(c);
cairo_set_source_rgba(c,1.,0,0,.25);
cairo_fill(c);
}
}break;
case OC_MODE_INTER_NOMV:{
if(_dec->telemetry_mbmode&0x01){
cairo_set_source_rgba(c,0,0,1.,.5);
cairo_rectangle(c,x+2.5,y+2.5,11,11);
cairo_stroke_preserve(c);
cairo_set_source_rgba(c,0,0,1.,.25);
cairo_fill(c);
}
}break;
case OC_MODE_INTER_MV:{
if(_dec->telemetry_mbmode&0x04){
cairo_rectangle(c,x+2.5,y+2.5,11,11);
cairo_set_source_rgba(c,0,1.,0,.5);
cairo_stroke(c);
}
if(_dec->telemetry_mv&0x04){
cairo_move_to(c,x+8+frag_mvx,y+8-frag_mvy);
cairo_set_source_rgba(c,1.,1.,1.,.9);
cairo_set_line_width(c,3.);
cairo_line_to(c,x+8+frag_mvx*.66,y+8-frag_mvy*.66);
cairo_stroke_preserve(c);
cairo_set_line_width(c,2.);
cairo_line_to(c,x+8+frag_mvx*.33,y+8-frag_mvy*.33);
cairo_stroke_preserve(c);
cairo_set_line_width(c,1.);
cairo_line_to(c,x+8,y+8);
cairo_stroke(c);
}
}break;
case OC_MODE_INTER_MV_LAST:{
if(_dec->telemetry_mbmode&0x08){
cairo_rectangle(c,x+2.5,y+2.5,11,11);
cairo_set_source_rgba(c,0,1.,0,.5);
cairo_move_to(c,x+13.5,y+2.5);
cairo_line_to(c,x+2.5,y+8);
cairo_line_to(c,x+13.5,y+13.5);
cairo_stroke(c);
}
if(_dec->telemetry_mv&0x08){
cairo_move_to(c,x+8+frag_mvx,y+8-frag_mvy);
cairo_set_source_rgba(c,1.,1.,1.,.9);
cairo_set_line_width(c,3.);
cairo_line_to(c,x+8+frag_mvx*.66,y+8-frag_mvy*.66);
cairo_stroke_preserve(c);
cairo_set_line_width(c,2.);
cairo_line_to(c,x+8+frag_mvx*.33,y+8-frag_mvy*.33);
cairo_stroke_preserve(c);
cairo_set_line_width(c,1.);
cairo_line_to(c,x+8,y+8);
cairo_stroke(c);
}
}break;
case OC_MODE_INTER_MV_LAST2:{
if(_dec->telemetry_mbmode&0x10){
cairo_rectangle(c,x+2.5,y+2.5,11,11);
cairo_set_source_rgba(c,0,1.,0,.5);
cairo_move_to(c,x+8,y+2.5);
cairo_line_to(c,x+2.5,y+8);
cairo_line_to(c,x+8,y+13.5);
cairo_move_to(c,x+13.5,y+2.5);
cairo_line_to(c,x+8,y+8);
cairo_line_to(c,x+13.5,y+13.5);
cairo_stroke(c);
}
if(_dec->telemetry_mv&0x10){
cairo_move_to(c,x+8+frag_mvx,y+8-frag_mvy);
cairo_set_source_rgba(c,1.,1.,1.,.9);
cairo_set_line_width(c,3.);
cairo_line_to(c,x+8+frag_mvx*.66,y+8-frag_mvy*.66);
cairo_stroke_preserve(c);
cairo_set_line_width(c,2.);
cairo_line_to(c,x+8+frag_mvx*.33,y+8-frag_mvy*.33);
cairo_stroke_preserve(c);
cairo_set_line_width(c,1.);
cairo_line_to(c,x+8,y+8);
cairo_stroke(c);
}
}break;
case OC_MODE_GOLDEN_NOMV:{
if(_dec->telemetry_mbmode&0x20){
cairo_set_source_rgba(c,1.,1.,0,.5);
cairo_rectangle(c,x+2.5,y+2.5,11,11);
cairo_stroke_preserve(c);
cairo_set_source_rgba(c,1.,1.,0,.25);
cairo_fill(c);
}
}break;
case OC_MODE_GOLDEN_MV:{
if(_dec->telemetry_mbmode&0x40){
cairo_rectangle(c,x+2.5,y+2.5,11,11);
cairo_set_source_rgba(c,1.,1.,0,.5);
cairo_stroke(c);
}
if(_dec->telemetry_mv&0x40){
cairo_move_to(c,x+8+frag_mvx,y+8-frag_mvy);
cairo_set_source_rgba(c,1.,1.,1.,.9);
cairo_set_line_width(c,3.);
cairo_line_to(c,x+8+frag_mvx*.66,y+8-frag_mvy*.66);
cairo_stroke_preserve(c);
cairo_set_line_width(c,2.);
cairo_line_to(c,x+8+frag_mvx*.33,y+8-frag_mvy*.33);
cairo_stroke_preserve(c);
cairo_set_line_width(c,1.);
cairo_line_to(c,x+8,y+8);
cairo_stroke(c);
}
}break;
case OC_MODE_INTER_MV_FOUR:{
if(_dec->telemetry_mbmode&0x80){
cairo_rectangle(c,x+2.5,y+2.5,4,4);
cairo_rectangle(c,x+9.5,y+2.5,4,4);
cairo_rectangle(c,x+2.5,y+9.5,4,4);
cairo_rectangle(c,x+9.5,y+9.5,4,4);
cairo_set_source_rgba(c,0,1.,0,.5);
cairo_stroke(c);
}
fragi=mb_maps[mbi][0][0];
if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
frag_mvx=OC_MV_X(frag_mvs[fragi]);
frag_mvx=OC_MV_Y(frag_mvs[fragi]);
cairo_move_to(c,x+4+frag_mvx,y+12-frag_mvy);
cairo_set_source_rgba(c,1.,1.,1.,.9);
cairo_set_line_width(c,3.);
cairo_line_to(c,x+4+frag_mvx*.66,y+12-frag_mvy*.66);
cairo_stroke_preserve(c);
cairo_set_line_width(c,2.);
cairo_line_to(c,x+4+frag_mvx*.33,y+12-frag_mvy*.33);
cairo_stroke_preserve(c);
cairo_set_line_width(c,1.);
cairo_line_to(c,x+4,y+12);
cairo_stroke(c);
}
fragi=mb_maps[mbi][0][1];
if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
frag_mvx=OC_MV_X(frag_mvs[fragi]);
frag_mvx=OC_MV_Y(frag_mvs[fragi]);
cairo_move_to(c,x+12+frag_mvx,y+12-frag_mvy);
cairo_set_source_rgba(c,1.,1.,1.,.9);
cairo_set_line_width(c,3.);
cairo_line_to(c,x+12+frag_mvx*.66,y+12-frag_mvy*.66);
cairo_stroke_preserve(c);
cairo_set_line_width(c,2.);
cairo_line_to(c,x+12+frag_mvx*.33,y+12-frag_mvy*.33);
cairo_stroke_preserve(c);
cairo_set_line_width(c,1.);
cairo_line_to(c,x+12,y+12);
cairo_stroke(c);
}
fragi=mb_maps[mbi][0][2];
if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
frag_mvx=OC_MV_X(frag_mvs[fragi]);
frag_mvx=OC_MV_Y(frag_mvs[fragi]);
cairo_move_to(c,x+4+frag_mvx,y+4-frag_mvy);
cairo_set_source_rgba(c,1.,1.,1.,.9);
cairo_set_line_width(c,3.);
cairo_line_to(c,x+4+frag_mvx*.66,y+4-frag_mvy*.66);
cairo_stroke_preserve(c);
cairo_set_line_width(c,2.);
cairo_line_to(c,x+4+frag_mvx*.33,y+4-frag_mvy*.33);
cairo_stroke_preserve(c);
cairo_set_line_width(c,1.);
cairo_line_to(c,x+4,y+4);
cairo_stroke(c);
}
fragi=mb_maps[mbi][0][3];
if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
frag_mvx=OC_MV_X(frag_mvs[fragi]);
frag_mvx=OC_MV_Y(frag_mvs[fragi]);
cairo_move_to(c,x+12+frag_mvx,y+4-frag_mvy);
cairo_set_source_rgba(c,1.,1.,1.,.9);
cairo_set_line_width(c,3.);
cairo_line_to(c,x+12+frag_mvx*.66,y+4-frag_mvy*.66);
cairo_stroke_preserve(c);
cairo_set_line_width(c,2.);
cairo_line_to(c,x+12+frag_mvx*.33,y+4-frag_mvy*.33);
cairo_stroke_preserve(c);
cairo_set_line_width(c,1.);
cairo_line_to(c,x+12,y+4);
cairo_stroke(c);
}
}break;
}
}
}
if(_dec->telemetry_qi&0x2){
cairo_set_line_cap(c,CAIRO_LINE_CAP_SQUARE);
for(bi=0;bi<4;bi++){
ptrdiff_t fragi;
int qiv;
int xp;
int yp;
xp=x+(bi&1)*8;
yp=y+8-(bi&2)*4;
fragi=mb_maps[mbi][0][bi];
if(fragi>=0&&frags[fragi].coded){
qiv=qim[frags[fragi].qii];
cairo_set_line_width(c,3.);
cairo_set_source_rgba(c,0.,0.,0.,.5);
switch(qiv){
case 2:{
if((bi&1)^((bi&2)>>1)){
cairo_move_to(c,xp+2.5,yp+1.5);
cairo_line_to(c,xp+2.5,yp+3.5);
cairo_move_to(c,xp+1.5,yp+2.5);
cairo_line_to(c,xp+3.5,yp+2.5);
cairo_move_to(c,xp+5.5,yp+4.5);
cairo_line_to(c,xp+5.5,yp+6.5);
cairo_move_to(c,xp+4.5,yp+5.5);
cairo_line_to(c,xp+6.5,yp+5.5);
cairo_stroke_preserve(c);
cairo_set_source_rgba(c,0.,1.,1.,1.);
}
else{
cairo_move_to(c,xp+5.5,yp+1.5);
cairo_line_to(c,xp+5.5,yp+3.5);
cairo_move_to(c,xp+4.5,yp+2.5);
cairo_line_to(c,xp+6.5,yp+2.5);
cairo_move_to(c,xp+2.5,yp+4.5);
cairo_line_to(c,xp+2.5,yp+6.5);
cairo_move_to(c,xp+1.5,yp+5.5);
cairo_line_to(c,xp+3.5,yp+5.5);
cairo_stroke_preserve(c);
cairo_set_source_rgba(c,0.,1.,1.,1.);
}
}break;
case -2:{
cairo_move_to(c,xp+2.5,yp+2.5);
cairo_line_to(c,xp+5.5,yp+2.5);
cairo_move_to(c,xp+2.5,yp+5.5);
cairo_line_to(c,xp+5.5,yp+5.5);
cairo_stroke_preserve(c);
cairo_set_source_rgba(c,1.,1.,1.,1.);
}break;
case 1:{
if((bi&2)==0)yp-=2;
if((bi&1)==0)xp-=2;
cairo_move_to(c,xp+4.5,yp+2.5);
cairo_line_to(c,xp+4.5,yp+6.5);
cairo_move_to(c,xp+2.5,yp+4.5);
cairo_line_to(c,xp+6.5,yp+4.5);
cairo_stroke_preserve(c);
cairo_set_source_rgba(c,.1,1.,.3,1.);
break;
}
case -1:{
cairo_move_to(c,xp+2.5,yp+4.5);
cairo_line_to(c,xp+6.5,yp+4.5);
cairo_stroke_preserve(c);
cairo_set_source_rgba(c,1.,.3,.1,1.);
}break;
default:continue;
}
cairo_set_line_width(c,1.);
cairo_stroke(c);
}
}
}
col2++;
if((col2>>1)>=_dec->state.nhmbs){
col2=0;
row2+=2;
}
}
if(_dec->telemetry_bits){
int widths[6];
int fpsn;
int fpsd;
int mult;
int fullw;
int padw;
int i;
fpsn=_dec->state.info.fps_numerator;
fpsd=_dec->state.info.fps_denominator;
mult=(_dec->telemetry_bits>=0xFF?1:_dec->telemetry_bits);
fullw=250.f*h*fpsd*mult/fpsn;
padw=w-24;
if(_dec->telemetry_frame_bytes<0||
_dec->telemetry_frame_bytes==OC_LOTS_OF_BITS){
_dec->telemetry_frame_bytes=0;
}
if(_dec->telemetry_coding_bytes<0||
_dec->telemetry_coding_bytes>_dec->telemetry_frame_bytes){
_dec->telemetry_coding_bytes=0;
}
if(_dec->telemetry_mode_bytes<0||
_dec->telemetry_mode_bytes>_dec->telemetry_frame_bytes){
_dec->telemetry_mode_bytes=0;
}
if(_dec->telemetry_mv_bytes<0||
_dec->telemetry_mv_bytes>_dec->telemetry_frame_bytes){
_dec->telemetry_mv_bytes=0;
}
if(_dec->telemetry_qi_bytes<0||
_dec->telemetry_qi_bytes>_dec->telemetry_frame_bytes){
_dec->telemetry_qi_bytes=0;
}
if(_dec->telemetry_dc_bytes<0||
_dec->telemetry_dc_bytes>_dec->telemetry_frame_bytes){
_dec->telemetry_dc_bytes=0;
}
widths[0]=padw*
(_dec->telemetry_frame_bytes-_dec->telemetry_coding_bytes)/fullw;
widths[1]=padw*
(_dec->telemetry_coding_bytes-_dec->telemetry_mode_bytes)/fullw;
widths[2]=padw*
(_dec->telemetry_mode_bytes-_dec->telemetry_mv_bytes)/fullw;
widths[3]=padw*(_dec->telemetry_mv_bytes-_dec->telemetry_qi_bytes)/fullw;
widths[4]=padw*(_dec->telemetry_qi_bytes-_dec->telemetry_dc_bytes)/fullw;
widths[5]=padw*(_dec->telemetry_dc_bytes)/fullw;
for(i=0;i<6;i++)if(widths[i]>w)widths[i]=w;
cairo_set_source_rgba(c,.0,.0,.0,.6);
cairo_rectangle(c,10,h-33,widths[0]+1,5);
cairo_rectangle(c,10,h-29,widths[1]+1,5);
cairo_rectangle(c,10,h-25,widths[2]+1,5);
cairo_rectangle(c,10,h-21,widths[3]+1,5);
cairo_rectangle(c,10,h-17,widths[4]+1,5);
cairo_rectangle(c,10,h-13,widths[5]+1,5);
cairo_fill(c);
cairo_set_source_rgb(c,1,0,0);
cairo_rectangle(c,10.5,h-32.5,widths[0],4);
cairo_fill(c);
cairo_set_source_rgb(c,0,1,0);
cairo_rectangle(c,10.5,h-28.5,widths[1],4);
cairo_fill(c);
cairo_set_source_rgb(c,0,0,1);
cairo_rectangle(c,10.5,h-24.5,widths[2],4);
cairo_fill(c);
cairo_set_source_rgb(c,.6,.4,.0);
cairo_rectangle(c,10.5,h-20.5,widths[3],4);
cairo_fill(c);
cairo_set_source_rgb(c,.3,.3,.3);
cairo_rectangle(c,10.5,h-16.5,widths[4],4);
cairo_fill(c);
cairo_set_source_rgb(c,.5,.5,.8);
cairo_rectangle(c,10.5,h-12.5,widths[5],4);
cairo_fill(c);
}
if(_dec->telemetry_qi&0x1){
cairo_text_extents_t extents;
char buffer[10];
int p;
int y;
p=0;
y=h-7.5;
if(_dec->state.qis[0]>=10)buffer[p++]=48+_dec->state.qis[0]/10;
buffer[p++]=48+_dec->state.qis[0]%10;
if(_dec->state.nqis>=2){
buffer[p++]=' ';
if(_dec->state.qis[1]>=10)buffer[p++]=48+_dec->state.qis[1]/10;
buffer[p++]=48+_dec->state.qis[1]%10;
}
if(_dec->state.nqis==3){
buffer[p++]=' ';
if(_dec->state.qis[2]>=10)buffer[p++]=48+_dec->state.qis[2]/10;
buffer[p++]=48+_dec->state.qis[2]%10;
}
buffer[p++]='\0';
cairo_select_font_face(c,"sans",
CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(c,18);
cairo_text_extents(c,buffer,&extents);
cairo_set_source_rgb(c,1,1,1);
cairo_move_to(c,w-extents.x_advance-10,y);
cairo_show_text(c,buffer);
cairo_set_source_rgb(c,0,0,0);
cairo_move_to(c,w-extents.x_advance-10,y);
cairo_text_path(c,buffer);
cairo_set_line_width(c,.8);
cairo_set_line_join(c,CAIRO_LINE_JOIN_ROUND);
cairo_stroke(c);
}
cairo_destroy(c);
}
_ycbcr[0].data=_dec->telemetry_frame_data;
_ycbcr[0].stride=_ycbcr[0].width;
_ycbcr[1].data=_ycbcr[0].data+h*_ycbcr[0].stride;
_ycbcr[1].stride=_ycbcr[1].width;
_ycbcr[2].data=_ycbcr[1].data+(h>>vdec)*_ycbcr[1].stride;
_ycbcr[2].stride=_ycbcr[2].width;
y_row=_ycbcr[0].data;
u_row=_ycbcr[1].data;
v_row=_ycbcr[2].data;
rgb_row=data;
switch(_dec->state.info.pixel_fmt){
case TH_PF_420:{
for(y=0;y<h;y+=2){
unsigned char *y_row2;
unsigned char *rgb_row2;
y_row2=y_row+_ycbcr[0].stride;
rgb_row2=rgb_row+cstride;
for(x=0;x<w;x+=2){
int y;
int u;
int v;
y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
+24966*rgb_row[4*x+0]+4207500)/255000;
y_row[x]=OC_CLAMP255(y);
y=(65481*rgb_row[4*x+6]+128553*rgb_row[4*x+5]
+24966*rgb_row[4*x+4]+4207500)/255000;
y_row[x+1]=OC_CLAMP255(y);
y=(65481*rgb_row2[4*x+2]+128553*rgb_row2[4*x+1]
+24966*rgb_row2[4*x+0]+4207500)/255000;
y_row2[x]=OC_CLAMP255(y);
y=(65481*rgb_row2[4*x+6]+128553*rgb_row2[4*x+5]
+24966*rgb_row2[4*x+4]+4207500)/255000;
y_row2[x+1]=OC_CLAMP255(y);
u=(-8372*(rgb_row[4*x+2]+rgb_row[4*x+6]
+rgb_row2[4*x+2]+rgb_row2[4*x+6])
-16436*(rgb_row[4*x+1]+rgb_row[4*x+5]
+rgb_row2[4*x+1]+rgb_row2[4*x+5])
+24808*(rgb_row[4*x+0]+rgb_row[4*x+4]
+rgb_row2[4*x+0]+rgb_row2[4*x+4])+29032005)/225930;
v=(39256*(rgb_row[4*x+2]+rgb_row[4*x+6]
+rgb_row2[4*x+2]+rgb_row2[4*x+6])
-32872*(rgb_row[4*x+1]+rgb_row[4*x+5]
+rgb_row2[4*x+1]+rgb_row2[4*x+5])
-6384*(rgb_row[4*x+0]+rgb_row[4*x+4]
+rgb_row2[4*x+0]+rgb_row2[4*x+4])+45940035)/357510;
u_row[x>>1]=OC_CLAMP255(u);
v_row[x>>1]=OC_CLAMP255(v);
}
y_row+=_ycbcr[0].stride<<1;
u_row+=_ycbcr[1].stride;
v_row+=_ycbcr[2].stride;
rgb_row+=cstride<<1;
}
}break;
case TH_PF_422:{
for(y=0;y<h;y++){
for(x=0;x<w;x+=2){
int y;
int u;
int v;
y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
+24966*rgb_row[4*x+0]+4207500)/255000;
y_row[x]=OC_CLAMP255(y);
y=(65481*rgb_row[4*x+6]+128553*rgb_row[4*x+5]
+24966*rgb_row[4*x+4]+4207500)/255000;
y_row[x+1]=OC_CLAMP255(y);
u=(-16744*(rgb_row[4*x+2]+rgb_row[4*x+6])
-32872*(rgb_row[4*x+1]+rgb_row[4*x+5])
+49616*(rgb_row[4*x+0]+rgb_row[4*x+4])+29032005)/225930;
v=(78512*(rgb_row[4*x+2]+rgb_row[4*x+6])
-65744*(rgb_row[4*x+1]+rgb_row[4*x+5])
-12768*(rgb_row[4*x+0]+rgb_row[4*x+4])+45940035)/357510;
u_row[x>>1]=OC_CLAMP255(u);
v_row[x>>1]=OC_CLAMP255(v);
}
y_row+=_ycbcr[0].stride;
u_row+=_ycbcr[1].stride;
v_row+=_ycbcr[2].stride;
rgb_row+=cstride;
}
}break;
default:{
for(y=0;y<h;y++){
for(x=0;x<w;x++){
int y;
int u;
int v;
y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
+24966*rgb_row[4*x+0]+4207500)/255000;
u=(-33488*rgb_row[4*x+2]-65744*rgb_row[4*x+1]
+99232*rgb_row[4*x+0]+29032005)/225930;
v=(157024*rgb_row[4*x+2]-131488*rgb_row[4*x+1]
-25536*rgb_row[4*x+0]+45940035)/357510;
y_row[x]=OC_CLAMP255(y);
u_row[x]=OC_CLAMP255(u);
v_row[x]=OC_CLAMP255(v);
}
y_row+=_ycbcr[0].stride;
u_row+=_ycbcr[1].stride;
v_row+=_ycbcr[2].stride;
rgb_row+=cstride;
}
}break;
}
cairo_surface_destroy(cs);
}
#endif
int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
ogg_int64_t *_granpos){ … }
int th_decode_ycbcr_out(th_dec_ctx *_dec,th_ycbcr_buffer _ycbcr){ … }