/****************************************************************************/ /* This is the source file for my frame C++ class, which is part of my */ /* Mpeg editor programme. */ /* */ /* This class desribes a YUV frame, with subsampled Cr & Cb frames, as used */ /* in Mpeg. */ /* (c)1994 Alexis 'Milamber' Ashley */ /****************************************************************************/ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "frame.H" #include #include #include #ifndef NO_INET #include #endif const long frame::preamble = 0xAA55; frame::frame(unsigned int height, unsigned int width) { /* Setup the three structures: luminance, Cr and Cb */ _Lum.height = height; _Lum.width = width; _Lum.length = width*height; _Lum.data = new byte[_Lum.length]; assert(_Lum.data!=NULL); _Cr.height = height/2; _Cr.width = width/2; _Cr.length = width*height/4; _Cr.data = new byte[_Cr.length]; assert(_Cr.data!=NULL); _Cb.height = height/2; _Cb.width = width/2; _Cb.length = width*height/4; _Cb.data = new byte[_Cb.length]; assert(_Cb.data!=NULL); } frame::frame(unsigned int height, unsigned int width,byte lum,byte cr,byte cb) { /* Setup the three structures: luminance, Cr and Cb */ _Lum.height = height; _Lum.width = width; _Lum.length = width*height; _Lum.data = new byte[_Lum.length]; assert(_Lum.data!=NULL); memset(_Lum.data,lum,_Lum.length); _Cr.height = height/2; _Cr.width = width/2; _Cr.length = width*height/4; _Cr.data = new byte[_Cr.length]; assert(_Cr.data!=NULL); memset(_Cr.data,cr,_Cr.length); _Cb.height = height/2; _Cb.width = width/2; _Cb.length = width*height/4; _Cb.data = new byte[_Cb.length]; assert(_Cb.data!=NULL); memset(_Cb.data,cb,_Cb.length); } frame::frame(const frame &source) { _Lum.height=source._Lum.height; _Lum.width=source._Lum.width; _Lum.length=source._Lum.length; _Lum.data = new byte[_Lum.length]; assert(_Lum.data!=NULL); set_lum(source._Lum.data); _Cr.height=source._Cr.height; _Cr.width=source._Cr.width; _Cr.length=source._Cr.length; _Cr.data = new byte[_Cr.length]; assert(_Cr.data!=NULL); set_Cr(source._Cr.data); _Cb.height=source._Cb.height; _Cb.width=source._Cb.width; _Cb.length=source._Cb.length; _Cb.data = new byte[_Cb.length]; assert(_Cb.data!=NULL); set_Cb(source._Cb.data); } frame::~frame(void) { delete _Lum.data; delete _Cr.data; delete _Cb.data; } bool frame::set_lum(const byte *l) { memcpy(_Lum.data,l,_Lum.length); return(true); } bool frame::set_Cr(const byte *cr) { memcpy(_Cr.data,cr,_Cr.length); return(true); } bool frame::set_Cb(const byte *cb) { memcpy(_Cb.data,cb,_Cb.length); return(true); } unsigned int frame::height(void) const { return(_Lum.height); } unsigned int frame::width(void) const { return(_Lum.width); } byte *frame::lum_ptr(void) { return(_Lum.data); } byte *frame::Cr_ptr(void) { return(_Cr.data); } byte *frame::Cb_ptr(void) { return(_Cb.data); } frame & frame::operator=(const frame &source) { if(_Lum.height!=source._Lum.height || _Lum.width!=source._Lum.width) { delete _Lum.data; _Lum.height=source._Lum.height; _Lum.width=source._Lum.width; _Lum.length=source._Lum.length; _Lum.data = new byte[_Lum.length]; assert(_Lum.data!=NULL); } set_lum(source._Lum.data); if(_Cr.height!=source._Cr.height || _Cr.width!=source._Cr.width) { delete _Cr.data; _Cr.height=source._Cr.height; _Cr.width=source._Cr.width; _Cr.length=source._Cr.length; _Cr.data = new byte[_Cr.length]; assert(_Cr.data!=NULL); } set_Cr(source._Cr.data); if(_Cb.height!=source._Cb.height || _Cb.width!=source._Cb.width) { delete _Cb.data; _Cb.height=source._Cb.height; _Cb.width=source._Cb.width; _Cb.length=source._Cb.length; _Cb.data = new byte[_Cb.length]; assert(_Cb.data!=NULL); } set_Cb(source._Cb.data); return *this; } /********************* YUV frame format **********************************/ /* There seems to be no standard for saving YUV frames, so here's my */ /* own standard. */ /* */ /* preamble 32bits 0x0000AA55, big endian ordering */ /* height 32bits big endian ordering */ /* width 32bits big endian ordering */ /* */ /* Lum plane height*width 8 bit octets */ /* Cr plane height*width/4 8 bit octets */ /* Cb plane height*width/4 8 bit octets */ /* */ /*************************************************************************/ fstream & operator<<(fstream &fs, const frame &f) { unsigned long int preamble, height, width; preamble = htonl(f.preamble); height = htonl(f._Lum.height); width = htonl(f._Lum.width); fs.write((char *)&preamble,sizeof(preamble) ); fs.write((char *)&height,sizeof(height) ); fs.write((char *)&width,sizeof(width) ); fs.write((char *)f._Lum.data, f._Lum.length); fs.write((char *)f._Cr.data, f._Cr.length); fs.write((char *)f._Cb.data, f._Cb.length); return fs; } fstream & operator>>(fstream &fs, frame &f) { unsigned long int preamble, height, width; fs.read((char *)&preamble,sizeof(preamble) ); fs.read((char *)&height,sizeof(height) ); fs.read((char *)&width,sizeof(width) ); preamble = ntohl(preamble); height = ntohl(height); width = ntohl(width); if(preamble!=f.preamble) { cout << "Invalid YUV frame, skipping\n"; cout << "Height = " << height << " Width = " << width << endl; memset(f._Lum.data,0,f._Lum.length); memset(f._Cr.data,128,f._Cr.length); memset(f._Cb.data,128,f._Cb.length); return fs; } if(f._Lum.height!=height || f._Lum.width!=width) { delete f._Lum.data; f._Lum.data = new byte[width*height]; assert(f._Lum.data!=NULL); } f._Lum.height = height; f._Lum.width = width; f._Lum.length = width*height; if( f._Cr.height!=(height/2) || f._Cr.width!=(width/2) ) { delete f._Cr.data; f._Cr.data = new byte[width*height/4]; assert(f._Cr.data!=NULL); } f._Cr.height = height/2; f._Cr.width = width/2; f._Cr.length = width*height/4; if( f._Cb.height!=(height/2) || f._Cb.width!=(width/2) ) { delete f._Cb.data; f._Cb.data = new byte[width*height/4]; assert(f._Cb.data!=NULL); } f._Cb.height = height/2; f._Cb.width = width/2; f._Cb.length = width*height/4; fs.read((char *)f._Lum.data, f._Lum.length); fs.read((char *)f._Cr.data, f._Cr.length); fs.read((char *)f._Cb.data, f._Cb.length); return fs; }