#include "dsputil.h" #include "avcodec.h" //#define DEBUG struct AVCodecContextPlus : public AVCodecContext { AVPicture my_picture; }; AVCodecContextPlus * make_my_av_ctx( int width, int height ) { #ifdef DEBUG // check that our globals are initialized printf( "clear_blocks is at 0x%08X", (void*)clear_blocks ); #endif AVCodecContextPlus * ac = (AVCodecContextPlus*)av_mallocz( sizeof( AVCodecContextPlus ) ); ac->frame_rate = 1; ac->width = width; ac->height = height; ac->aspect_ratio_info = FF_ASPECT_SQUARE; ac->pix_fmt = PIX_FMT_ANY; #ifdef DEBUG printf( "make_my_av_ctx: width %d height %d\n", width, height ); #endif avcodec_open(ac, &h263i_decoder); return ac; } void free_my_av_ctx( AVCodecContextPlus * avctx ) { avcodec_close( avctx ); free( avctx ); } inline void memcpyupd( void *& dst, void *& src, int len ) { memcpy( dst, src, len ); (char*&)dst += len; (char*&)src += len; } #define SCALE_BITS 10 #define C_Y (76309 >> (16 - SCALE_BITS)) #define C_RV (117504 >> (16 - SCALE_BITS)) #define C_BU (138453 >> (16 - SCALE_BITS)) #define C_GU (13954 >> (16 - SCALE_BITS)) #define C_GV (34903 >> (16 - SCALE_BITS)) #define RGBOUT(r, g, b, y1) \ { \ y = (y1 - 16) * C_Y; \ r = cm[(y + r_add) >> SCALE_BITS]; \ g = cm[(y + g_add) >> SCALE_BITS]; \ b = cm[(y + b_add) >> SCALE_BITS]; \ } extern UINT8 cropTbl[256 + 2 * MAX_NEG_CROP]; long process_my_av_ctx( AVCodecContextPlus * avctx, unsigned char * inData, int inSize, unsigned char * outData, long outRowBytes ) { int got_picture = 0; int len = avcodec_decode_video(avctx, &avctx->my_picture, &got_picture, inData, inSize); if (len < 0) { printf( "Error decoding frame %d\n", avctx->frame_number ); return inSize; // always return inSize so we don't get stuck in a loop } if (got_picture) { UINT8 * midData[3] = { avctx->my_picture.data[0], avctx->my_picture.data[1], avctx->my_picture.data[2] }; long midRowBytes[3] = { avctx->my_picture.linesize[0], avctx->my_picture.linesize[1], avctx->my_picture.linesize[2] }; //long outDataRowDiff = outRowBytes-(midRowBytes[0]+midRowBytes[1]+midRowBytes[2]); int height = avctx->height; int width = avctx->width; int hwidth = width >> 1; /* for (int y = 0; y < height; y++) { UINT8 * outDataRow = outData; //memcpyupd( outData, midData[0], midRowBytes[0] ); //memcpyupd( outData, midData[1], midRowBytes[1] ); //memcpyupd( outData, midData[2], midRowBytes[2] ); for (int x = 0; x < hwidth; x++) { *((UINT32*&)outData)++ = (( ((midData[0][0]) << 8) | ((*midData[1]) & 0xf0) | ((*midData[2]) >> 4) )<< 16) | (( ((midData[0][1]) << 8) | (((*midData[1]) << 4) & 0xf0) | ((*midData[2]) & 0x0f) )); midData[0]+=2; midData[1]++; midData[2]++; } //outData += outDataRowDiff; outData = outDataRow + outRowBytes; // there is a quarter the u/Cb info than y/Y info // (should be half...?). same deal with y/Cr if (!(y&1)) { midData[1] -= midRowBytes[1]; midData[2] -= midRowBytes[2]; } } */ UINT8 *cm = cropTbl + MAX_NEG_CROP; UINT8 * y1_ptr = midData[0]; UINT8 * cb_ptr = midData[1]; UINT8 * cr_ptr = midData[2]; for(;height > 0; height -= 2) { int y, cb, cr, r_add, g_add, b_add; UINT8 * d1 = outData; UINT8 * d2 = outData + outRowBytes; UINT8 * y2_ptr = y1_ptr + midRowBytes[0]; for(int w = hwidth; w > 0; w --) { cb = cb_ptr[0] - 128; cr = cr_ptr[0] - 128; r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); /* output 4 pixels */ RGBOUT(d1[1], d1[2], d1[3], y1_ptr[0]); RGBOUT(d1[5], d1[6], d1[7], y1_ptr[1]); RGBOUT(d2[1], d2[2], d2[3], y2_ptr[0]); RGBOUT(d2[5], d2[6], d2[7], y2_ptr[1]); // TODO: Find a nice way of interpolating cb and cr. d1 += 8; d2 += 8; y1_ptr += 2; y2_ptr += 2; cb_ptr++; cr_ptr++; } outData += outRowBytes + outRowBytes; y1_ptr += midRowBytes[0] + midRowBytes[0] - width; cb_ptr += midRowBytes[1] - hwidth; cr_ptr += midRowBytes[2] - hwidth; } } return inSize; }