static int nuv_decode_video(TCModuleInstance *self, vframe_list_t *inframe, vframe_list_t *outframe) { PrivateData *pd; uint8_t comptype, *encoded_frame; int in_framesize, out_framesize; int free_frame = 0; // set to 1 if we need to free the decompress buffer TC_MODULE_SELF_CHECK(self, "decode_video"); TC_MODULE_SELF_CHECK(inframe, "decode_video"); TC_MODULE_SELF_CHECK(outframe, "decode_video"); pd = self->userdata; if (!pd->dec_initted) { pd->width = inframe->video_buf[0]<<8 | inframe->video_buf[1]; pd->height = inframe->video_buf[2]<<8 | inframe->video_buf[3]; RTjpeg_init_decompress((uint32_t *)(inframe->video_buf+5), pd->width, pd->height); pd->dec_initted = 1; } comptype = inframe->video_buf[4]; encoded_frame = inframe->video_buf+5+sizeof(pd->cdata); in_framesize = inframe->video_size-5-sizeof(pd->cdata); out_framesize = pd->width*pd->height + (pd->width/2)*(pd->height/2)*2; if (comptype == '2' || comptype == '3') { /* Undo LZO compression */ uint8_t *decompressed_frame; lzo_uint len; decompressed_frame = tc_malloc(out_framesize); if (!decompressed_frame) { tc_log_error(MOD_NAME, "No memory for decompressed frame!"); return TC_ERROR; } if (lzo1x_decompress(encoded_frame, in_framesize, decompressed_frame, &len, NULL) == LZO_E_OK) { encoded_frame = decompressed_frame; in_framesize = len; free_frame = 1; } else { tc_log_warn(MOD_NAME, "Unable to decompress video frame"); tc_free(decompressed_frame); /* And try it as raw, just like rtjpeg_vid_plugin */ } /* Convert 2 -> 1, 3 -> 0 */ comptype ^= 3; } switch (comptype) { case '0': // Uncompressed YUV if (in_framesize > out_framesize) in_framesize = out_framesize; ac_memcpy(outframe->video_buf, encoded_frame, in_framesize); break; case '1': // RTjpeg-compressed data RTjpeg_decompressYUV420((int8_t *)encoded_frame, outframe->video_buf); break; case 'N': // Black frame memset(outframe->video_buf, 0, pd->width*pd->height); memset(outframe->video_buf + pd->width*pd->height, 128, (pd->width/2)*(pd->height/2)*2); break; case 'L': // Repeat last frame--leave videobuf alone // Should have been handled by demux! tc_log_warn(MOD_NAME, "BUG: 'L' frame not handled!"); break; default: tc_log_warn(MOD_NAME, "Unknown video compression type %c (%02X)", comptype >= ' ' && comptype <= '=' ? comptype : '?', comptype); break; } // switch (comptype) if (free_frame) tc_free(encoded_frame); outframe->video_size = out_framesize; return TC_OK; }
int main( int argc, char** argv ) { unsigned int w, h; int tmp; FILE* f; struct stat st; struct rtj_header hdr; __u8 *source; __u8 *target; if ( argc != 2 ) { print_help(); exit(0); } if ( stat( argv[1], &st ) != 0 ) { perror( "stat:" ); exit(1); } f = fopen( argv[1] , "r" ); if ( !rtj_read_header(&hdr,f) ) { fprintf( stderr, "This doesn't seem to be a RTJPEG header.\n" ); return 1; } w = hdr.width; h = hdr.height; source = malloc( w*h*3 ); /* size of YUV picture info */ assert( source != NULL ); tmp = fread( source, 1, w*h*3, f ); /* assert( tmp == w*h*3 ); */ fprintf( stderr, "Read %i bytes from file.\n", tmp ); RTjpeg_init_decompress( hdr.tbls, w, h ); target = malloc( w*h*3 ); RTjpeg_decompressYUV420( source, target ); if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { perror( "SDL_init:" ); exit(1); } /* setup signal handlers */ signal(SIGINT,sig_handler); atexit( SDL_Quit ); screen = SDL_SetVideoMode( w, h, 24, SDL_HWSURFACE ); SDL_EventState(SDL_KEYDOWN, SDL_ENABLE); SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE); assert( screen != NULL ); if ( SDL_MUSTLOCK( screen ) ) { if ( SDL_LockSurface(screen) < 0 ) { assert(0); exit(1); } } /* copy image to screen and convert to RGB32 */ RTjpeg_yuvrgb24( target, screen->pixels, w*3 ); if ( SDL_MUSTLOCK( screen ) ) { SDL_UnlockSurface(screen); } SDL_UpdateRect(screen, 0, 0, w, h); pause(); return 0; }
void decode_nuv( unsigned char *encoded, int encoded_size, unsigned char *decoded, int width, int height) { int r; unsigned int out_len = width * height + ( width * height ) / 2; struct rtframeheader *encodedh = ( struct rtframeheader* ) encoded; static unsigned char *buffer = 0; /* for RTJpeg with LZO decompress */ #ifdef KEEP_BUFFER static unsigned char *previous_buffer = 0; /* to support Last-frame-copy */ #endif // printf("frametype: %c, comtype: %c, encoded_size: %d, width: %d, height: %d\n", // encodedh->frametype, encodedh->comptype, encoded_size, width, height); le2me_rtframeheader(encodedh); switch(encodedh->frametype) { case 'D': /* additional data for compressors */ { /* tables are in encoded */ if (encodedh->comptype == 'R') { RTjpeg_init_decompress ( (unsigned long *)(encoded+12), width, height ); mp_msg(MSGT_DECVIDEO, MSGL_V, "Found RTjpeg tables (size: %d, width: %d, height: %d)\n", encoded_size-12, width, height); } break; } case 'V': { int in_len = encodedh->packetlength; #ifdef KEEP_BUFFER if (!previous_buffer) previous_buffer = ( unsigned char * ) malloc ( out_len + LZO_OUTPUT_PADDING ); #endif switch(encodedh->comptype) { case '0': /* raw YUV420 */ memcpy(decoded, encoded + 12, out_len); break; case '1': /* RTJpeg */ RTjpeg_decompressYUV420 ( ( __s8 * ) encoded + 12, decoded ); break; case '2': /* RTJpeg with LZO */ if (!buffer) buffer = ( unsigned char * ) malloc ( out_len + LZO_OUTPUT_PADDING ); if (!buffer) { mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Nuppelvideo: error decompressing\n"); break; } r = lzo1x_decode ( buffer, &out_len, encoded + 12, &in_len ); if ( r ) { mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Nuppelvideo: error decompressing\n"); break; } RTjpeg_decompressYUV420 ( ( __s8 * ) buffer, decoded ); break; case '3': /* raw YUV420 with LZO */ r = lzo1x_decode ( decoded, &out_len, encoded + 12, &in_len ); if ( r ) { mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Nuppelvideo: error decompressing\n"); break; } break; case 'N': /* black frame */ memset ( decoded, 0, width * height ); memset ( decoded + width * height, 127, width * height / 2); break; case 'L': /* copy last frame */ #ifdef KEEP_BUFFER memcpy ( decoded, previous_buffer, width*height*3/2); #endif break; } #ifdef KEEP_BUFFER memcpy(previous_buffer, decoded, width*height*3/2); #endif break; } default: mp_msg(MSGT_DECVIDEO, MSGL_V, "Nuppelvideo: unknwon frametype: %c\n", encodedh->frametype); } }