LossyDepthFrameReader::LossyDepthFrameReader(IO::File& sSource) :source(sSource), sourceHasTheora(false) { /* Read the frame size from the source: */ for(int i=0;i<2;++i) size[i]=source.read<Misc::UInt32>(); /* Read the stream header's size: */ size_t streamHeaderSize=source.read<Misc::UInt32>(); sourceHasTheora=streamHeaderSize>0; if(sourceHasTheora) { #if VIDEO_CONFIG_HAVE_THEORA /* Create the setup structures: */ Video::TheoraInfo theoraInfo; Video::TheoraComment theoraComments; Video::TheoraDecoder::Setup theoraSetup; /* Read and process all stream header packets: */ while(streamHeaderSize>0) { /* Read and process the next header packet: */ Video::TheoraPacket packet; packet.read(source); Video::TheoraDecoder::processHeader(packet,theoraInfo,theoraComments,theoraSetup); streamHeaderSize-=packet.getWireSize(); } /* Initialize the Theora decoder: */ theoraDecoder.init(theoraInfo,theoraSetup); #else /* Skip the stream header packets: */ source.skip<Misc::UInt8>(streamHeaderSize); #endif } }
FrameBuffer LossyDepthFrameReader::readNextFrame(void) { /* Create the result frame: */ FrameBuffer result(size[0],size[1],size[1]*size[0]*sizeof(FrameSource::DepthPixel)); /* Return a dummy frame if the file is over: */ if(source.eof()) { result.timeStamp=Math::Constants<double>::max; return result; } /* Read the frame's time stamp from the source: */ result.timeStamp=source.read<Misc::Float64>(); if(sourceHasTheora) { #if VIDEO_CONFIG_HAVE_THEORA /* Read and process a single Theora packet: */ { /* Read and process the next packet: */ Video::TheoraPacket packet; packet.read(source); theoraDecoder.processPacket(packet); } /* Extract the decompressed frame: */ Video::TheoraFrame theoraFrame; theoraDecoder.decodeFrame(theoraFrame); /* Convert the decompressed frame from Y'CbCr 4:2:0 to 11-bit depth: */ FrameSource::DepthPixel* resultRowPtr=result.getData<FrameSource::DepthPixel>(); const unsigned char* ypRowPtr=static_cast<const unsigned char*>(theoraFrame.planes[0].data)+theoraFrame.offsets[0]; const unsigned char* cbRowPtr=static_cast<const unsigned char*>(theoraFrame.planes[1].data)+theoraFrame.offsets[1]; const unsigned char* crRowPtr=static_cast<const unsigned char*>(theoraFrame.planes[2].data)+theoraFrame.offsets[2]; for(unsigned int y=0;y<size[1];y+=2) { FrameSource::DepthPixel* resultPtr=resultRowPtr; const unsigned char* ypPtr=ypRowPtr; const unsigned char* cbPtr=cbRowPtr; const unsigned char* crPtr=crRowPtr; for(unsigned int x=0;x<size[0];x+=2) { /* Assemble the block's 4 11-bit depth values from the 4 8-bit yp values and the 8-bit cb and cr values: */ resultPtr[0]=((FrameSource::DepthPixel(ypPtr[0])<<3)&0x7f8U)|(FrameSource::DepthPixel(*cbPtr)>>4); resultPtr[1]=((FrameSource::DepthPixel(ypPtr[1])<<3)&0x7f8U)|(FrameSource::DepthPixel(*cbPtr)&0x0fU); resultPtr[size[0]]=((FrameSource::DepthPixel(ypPtr[theoraFrame.planes[0].stride])<<3)&0x7f8U)|(FrameSource::DepthPixel(*cbPtr)>>4); resultPtr[size[0]+1]=((FrameSource::DepthPixel(ypPtr[theoraFrame.planes[0].stride+1])<<3)&0x7f8U)|(FrameSource::DepthPixel(*cbPtr)&0x0fU); /* Go to the next pixel block: */ resultPtr+=2; ypPtr+=2; ++cbPtr; ++crPtr; } /* Go to the next pixel block row: */ resultRowPtr+=size[0]*2; ypRowPtr+=theoraFrame.planes[0].stride*2; cbRowPtr+=theoraFrame.planes[1].stride; crRowPtr+=theoraFrame.planes[2].stride; } #else /********************** Skip one Theora packet: **********************/ /* Skip packet flags: */ source.skip<char>(1); /* Skip 64-bit granule position and packet number: */ source.skip<Misc::SInt64>(2); /* Read the packet data size: */ size_t packetSize=source.read<unsigned int>(); source.skip<Misc::UInt8>(packetSize); /* Initialize the frame to all invalid pixels: */ FrameSource::DepthPixel* resultPtr=result.getData<FrameSource::DepthPixel>(); for(unsigned int y=0;y<size[1];++y) for(unsigned int x=0;x<size[0];++x,++resultPtr) *resultPtr=FrameSource::invalidDepth; #endif } else {
FrameBuffer ColorFrameReader::readNextFrame(void) { /* Create the result frame: */ FrameBuffer result(size[0],size[1],size[1]*size[0]*3*sizeof(unsigned char)); /* Return a dummy frame if the file is over: */ if(source.eof()) { result.timeStamp=Math::Constants<double>::max; return result; } /* Read the frame's time stamp from the source: */ result.timeStamp=source.read<double>(); if(sourceHasTheora) { #if VIDEO_CONFIG_HAVE_THEORA /* Read and process a single Theora packet: */ { /* Read and process the next packet: */ Video::TheoraPacket packet; packet.read(source); theoraDecoder.processPacket(packet); } /* Extract the decompressed frame: */ Video::TheoraFrame theoraFrame; theoraDecoder.decodeFrame(theoraFrame); /* Convert the decompressed frame from Y'CbCr 4:2:0 to RGB: */ unsigned char* resultRowPtr=static_cast<unsigned char*>(result.getBuffer())+(size[1]-1)*size[0]*3; const unsigned char* ypRowPtr=static_cast<const unsigned char*>(theoraFrame.planes[0].data)+theoraFrame.offsets[0]; const unsigned char* cbRowPtr=static_cast<const unsigned char*>(theoraFrame.planes[1].data)+theoraFrame.offsets[1]; const unsigned char* crRowPtr=static_cast<const unsigned char*>(theoraFrame.planes[2].data)+theoraFrame.offsets[2]; for(unsigned int y=0; y<size[1]; y+=2) { unsigned char* resultPtr=resultRowPtr; const unsigned char* ypPtr=ypRowPtr; const unsigned char* cbPtr=cbRowPtr; const unsigned char* crPtr=crRowPtr; for(unsigned int x=0; x<size[0]; x+=2) { /* Convert the four pixels in the 2x2 block from Y'CbCr to RGB: */ unsigned char ypcbcr[3]; ypcbcr[0]=ypPtr[0]; ypcbcr[1]=*cbPtr; ypcbcr[2]=*crPtr; Video::ypcbcrToRgb(ypcbcr,resultPtr); ypcbcr[0]=ypPtr[1]; Video::ypcbcrToRgb(ypcbcr,resultPtr+3); ypcbcr[0]=ypPtr[theoraFrame.planes[0].stride]; Video::ypcbcrToRgb(ypcbcr,resultPtr-size[0]*3); ypcbcr[0]=ypPtr[theoraFrame.planes[0].stride+1]; Video::ypcbcrToRgb(ypcbcr,resultPtr-size[0]*3+3); /* Go to the next pixel: */ resultPtr+=2*3; ypPtr+=2; ++cbPtr; ++crPtr; } /* Go to the next row: */ resultRowPtr-=2*size[0]*3; ypRowPtr+=2*theoraFrame.planes[0].stride; cbRowPtr+=theoraFrame.planes[1].stride; crRowPtr+=theoraFrame.planes[2].stride; } #else /********************** Skip one Theora packet: **********************/ /* Skip packet flags: */ source.skip<char>(1); /* Skip 64-bit granule position and packet number: */ source.skip<Misc::SInt64>(2); /* Read the packet data size: */ size_t packetSize=source.read<unsigned int>(); source.skip<Misc::UInt8>(packetSize); /* Initialize the frame to 50% grey (why not?): */ unsigned char* resultPtr=static_cast<unsigned char*>(result.getBuffer()); for(unsigned int y=0; y<size[1]; ++y) for(unsigned int x=0; x<size[0]; ++x,resultPtr+=3) { resultPtr[0]=(unsigned char)(128); resultPtr[1]=(unsigned char)(128); resultPtr[2]=(unsigned char)(128); } #endif } else { /* Initialize the frame to 50% grey (why not?): */ unsigned char* resultPtr=static_cast<unsigned char*>(result.getBuffer()); for(unsigned int y=0; y<size[1]; ++y) for(unsigned int x=0; x<size[0]; ++x,resultPtr+=3) { resultPtr[0]=(unsigned char)(128); resultPtr[1]=(unsigned char)(128); resultPtr[2]=(unsigned char)(128); } } return result; }