Internet Engineering Task Force Michael F. Speer Audio-Video Transport Working Group Don Hoffman draft-ietf-avt-cellb-profile-04.txt Sun Microsystems, Inc. March 23, 1995 Expires: Sept 23rd, 1995 RTP Payload Format of CellB Video Encoding Status of this Memo This document is an Internet Draft. Internet Drafts are working documents of the Internet Engineering Task Force (IETF), its Areas, and its Working Groups. Note that other groups may also distribute working documents as Internet Drafts. Internet Drafts are draft documents valid for a maximum of six months. Internet Drafts may be updated, replaced, or obsoleted by other documents at any time. It is not appropriate to use Internet Drafts as reference material or to cite them other than as a ``working draft'' or ``work in progress.'' Please check the I-D abstract listing contained in each Internet Draft directory to learn the current status of this or any other Internet Draft. Distribution of this document is unlimited. Abstract This draft describes a packetization scheme for the CellB video encoding. The scheme proposed allow applications to transport CellB video flows over protocols used by RTP. This document is meant for implementors of video applications that want to use RTP and CellB. draft-ietf-avt-cellb-profile-04.txt [Page 1] INTERNET-DRAFT CellB Profile March 1994 0 Changes 1. Removed the description of the RTP fixed header. 2. Fixed up references to be current to relative internet-drafts. 3. Fixed the date. draft-ietf-avt-cellb-profile-04.txt [Page 2] INTERNET-DRAFT CellB Profile March 1994 1 Introduction The Cell image compression algorithm is a variable bit-rate video coding scheme. It provides "high" quality, low bit-rate image compression at low computational cost. The bytestream that is produced by the Cell encoder consists of instructional codes and information about the compressed image. For futher information on Cell compression technology, refer to [1]. Currently, there are two versions of the Cell compression technology: CellA and CellB. CellA is primarily designed for the encoding of stored video intended for local display, and will not be discussed in this memo. CellB, derived from CellA, has been optimized for network-based video applications. It is computationally symmetric in both encode and decode. CellB utilizes a fixed colormap and vector quantization techniques in the YUV color space to achieve compression. 2 Structure of the CellB Video Stream The CellB bytestream consists of cell codes, skip codes and quantization-table specific codes. These are now described. 2.1 CellB Cell Code Cell codes are 4 bytes in length, and describe a 4x4 pixel cell. There are two possible luminance (Y) levels for each cell, but only one pair of chrominance (UV) values. The CellB cell code is shown below: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0 M M M M M M M M M M M M M M M|U V U V U V U V|Y Y Y Y Y Y Y Y| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 4x4 Bitmask U/V Code Y/Y Code The first two bytes of the cell code are a bitmask. Each bit in the mask represents a pixel in a 16-pixel cell. Bit 0 represents the value of the upper right-hand pixel of the cell, and subsequent bits represent the pixels in row-major order. If a pixel's bit is set in the 4x4 Bitmask, then the pixel will be rendered with the pixel value . If the pixel's bit is not set in the bitmask, then the pixel's value will be rendered with the value . The bitmask for the cell is normalized so that the most significant bit is always 0 (i.e., corresponding to ). draft-ietf-avt-cellb-profile-04.txt [Page 3] INTERNET-DRAFT CellB Profile March 1994 The U/V field of the cell code represents the chrominance component. This code is in index into a table of vectors that represents two independent components of chrominance. The Y/Y field of the cell code represents two luminance values (Y(0) and Y(1)). This code is an index into a table of two-compoment luminance vectors. The derivation of the U/V and Y/Y tables is outside the scope of this memo. A complete discussion can be found in [1]. 2.2 CellB Skip Code The single byte CellB skip code tells the CellB decoder to skip the next S+1 cells in the current video frame being decoded. The maximum number of cells that can be skipped is 32. The format of the skip code is shown below. 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ |1 0 0 S S S S S| +-+-+-+-+-+-+-+-+ 2.3 CellB Y/Y Table Code The single byte "new Y/Y table" code is used to tell the decoder that the next 512 bytes are a new Y/Y quantization table. The code and the representation of the table are shown below. The sample encoder/decoder pair in this document do not implement this feature of the CellB compression. However, future CellB codecs may implement this feature. 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ |1 1 1 1 1 1 1 0| +-+-+-+-+-+-+-+-+ The format of the new Y/Y table is: 0 1 2 3 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Y1_000 | Y2_000 | Y1_001 | Y2_001 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ . . . draft-ietf-avt-cellb-profile-04.txt [Page 4] INTERNET-DRAFT CellB Profile March 1994 0 1 2 3 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Y1_254 | Y2_254 | Y1_255 | Y2_255 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2.4 CellB U/V Table Code The single byte "new U/V table" code is used to tell the decoder that the next 512 bytes represent a new U/V quantization table. The code is shown below. The sample encoder/decoder pair provided in this document do not implement this feature of the CellB compression. However, future CellB codecs may implement this feature. 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ |1 1 1 1 1 1 1 1| +-+-+-+-+-+-+-+-+ The bytes of the new U/V quantization table are arranged as: 0 1 2 3 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | U_000 | V_000 | U_001 | V_001 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ . . . 0 1 2 3 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | U_254 | V_254 | U_255 | V_255 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ draft-ietf-avt-cellb-profile-04.txt [Page 5] INTERNET-DRAFT CellB Profile March 1994 3 Network Packetization and Encapsulation 3.1 RTP Fixed Header Usage The RTP Packetization of the CellB Video uses the Fixed RTP header in standard way. It uses the Marker Bit to demark the end-of-frame boundary. This packetization makes of the pre-defined RTP timestamp in the RTP specification withi is the middle 32 bits of an NTP timestamp. Also, the Packet Type field in the RTP header is filled in with the Packet Type id for CellB Video. 3.2 CellB-specific Header Information The encapsulation and packetization of the CellB bytestream is designed to make the resulting packet stream robust to packet loss. To achieve this, an additional header is added to each RTP packet to uniquely identify the location of the first cell of the packet within the current frame. In addition, the width and height of the frame in pixels is carried in each CellB packet header. Although the size can only change between frames, it is carried in every packet to simplify the packet encoding. 0 1 2 3 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cell X Location | Cell Y Location | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Width of Image | Height of Image | +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | Compressed CellB Data | | .... | +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ All fields are 16-bit unsigned integers in network byte order, and are placed at the beginning of the payload for each RTP packet. The Cell X and the Cell Y Location coordinates are expressed as cell coordinates, not pixel coordinates. Since cells represent 4x4 blocks of pixels, the X or Y dimension of the cell coordinates range in value from 0 through 1/4 of the of the same dimension in pixel coordinates. 3.3 Packetization Rules A packet can be of any size chosen by the implementor, up to a full frame. All multi-byte codes must be completely contained within a packet. In general, the implementor should avoid packet sizes that result in fragmentation by the network. draft-ietf-avt-cellb-profile-04.txt [Page 6] INTERNET-DRAFT CellB Profile March 1994 4 Sample Codec The following code is placed here as sample codec for CellB. The code is integrated into NV release 3.3 and later. 4.1 Sample Encoder The C code included here represents a reference software encoder for CellB. For complete source refer to [3]. /* * Copyright (c) Sun Microsystems, Inc. 1992, 1993, 1994. All rights reserved. * * License is granted to copy, to use, and to make and to use derivative * works for research and evaluation purposes, provided that Sun Microsystems is * acknowledged in all documentation pertaining to any such copy or derivative * work. Sun Microsystems grants no other licenses expressed or implied. The * Sun Microsystems trade name should not be used in any advertising without * its written permission. * * This software is provided "as-is" without express or implied warranty of * any kind. These notices must be retained in any copies of any part of * this software. */ /* Header for CellB packet. */ static struct { u_int16 x, y; u_int16 w, h; } xilhdr; int CellB_Encode_Init(int width, int height) { int i,j; int size; u_int8 *dptr; size = height * width; cb_data = (u_int8 *)malloc(sizeof(u_int8) * size); if (!cb_data) return (0); size /= 16; cellkount = (u_int8 *)malloc(size*sizeof(u_int8)); cellhistory = (u_int32*)malloc(size*sizeof(u_int32)); for (i=0;i> 8; for (j = 0; j < 252; j++) { int index; int u1 = uvtable[j]; int v1 = u1 & 255; u1 = u1 >> 8; u1 = u1 - u0; v1 = v1 - v0; if (UVCLOSE(u1, v1)) { index = (i << 5) | (j >> 3); uvlookup[index] |= 1 << (j & 7); } } } /* .... initialize error mult table .... */ for (j = 0; j < 17; j++) { for (i = 0; i < 512; i++) { int index = i - 256; int absindex = (index < 0) ? -index : index; int tmp = absindex * j; tmp = (tmp > 255) ? 255 : tmp; error[j][i] = tmp; } } xilhdr.w = htons(width); xilhdr.h = htons(height); return 1; draft-ietf-avt-cellb-profile-04.txt [Page 8] INTERNET-DRAFT CellB Profile March 1994 } int CellB_Encode(uint8 *old_y_data, uint8 *cb_yy_data, int8 *cb_uv_data, int packlen, int aging_bytes, nv_xmitproc_t *callback) { u_int8 *data, *dataLim, *pack, *packLim; u_int16 cellx, celly, width; int len, nframes, pattern; int res; int x,y,k; int xmax = xilhdr.w/4; int ymax = xilhdr.h/4; u_int8 *tyy; signed char *tuv; int skipcount; int index; int bcnt; width = xilhdr.w>>2; len = width*12; data = cb_data; bcnt = 0; skipcount = 0; index = 0; tyy = cb_yy_data; tuv = cb_uv_data; for (y=0;y MAXSKIP) { *data++ = SKIPCODE + MAXSKIP - 1; bcnt += 1; skipcount -= MAXSKIP; } if (skipcount > 0) { *data++ = SKIPCODE + skipcount - 1; bcnt += 1; skipcount = 0; } *data++ = res >> 24; draft-ietf-avt-cellb-profile-04.txt [Page 9] INTERNET-DRAFT CellB Profile March 1994 *data++ = res >> 16; *data++ = res >> 8; *data++ = res; bcnt += 4; } index += 1; tyy += 4; tuv += 4; } tyy += len; tuv += len; } data = cb_data; len = bcnt; dataLim = data+len; cellx = 0; celly = 0; width = ntohs(xilhdr.w) >> 2; do { pack = data; packLim = data+packlen-4; xilhdr.x = htons(cellx); xilhdr.y = htons(celly); while ((data < packLim) && (data < dataLim)) { pattern = *data; if (pattern >= 128) { data++; cellx += (pattern-127); } else { data += 4; cellx++; } while (cellx >= width) { cellx -= width; celly++; } } /* Send out the packet. */ (*callback)((data < dataLim) ? 0 : 1, RTPCONT_CELLB, (u_int8 *)&xilhdr, sizeof(xilhdr), pack, data-pack); } while (data < dataLim); draft-ietf-avt-cellb-profile-04.txt [Page 10] INTERNET-DRAFT CellB Profile March 1994 return (len); } #define SetMaskBit(YVAL, BIT) if ((YVAL) < ymean) { ylo += (YVAL); tmp += 1; } else { yhi += (YVAL); mask += (1 << (BIT)); } u_int32 encode_cell(u_int8 *tyy, int8 *tuv, int stride) { register int ymean, uvindx; register u_int32 mask, yhi, ylo, tmp, yval; register u_int32 q0, q1, q2, q3; { register int umean, vmean; register signed int t0, t1, t2, t3; t0 = ((int *)tuv)[0]; t1 = ((int *)tuv)[stride]; t2 = ((int *)tuv)[stride+stride]; t3 = ((int *)tuv)[stride+stride+stride]; umean = (t0<<24)>>24; vmean = (t0<<16)>>24; umean += (t0<<8)>>24; vmean += t0>>24; umean += (t1<<24)>>24; vmean += (t1<<16)>>24; umean += (t1<<8)>>24; vmean += t1>>24; umean += (t2<<24)>>24; vmean += (t2<<16)>>24; umean += (t2<<8)>>24; vmean += t2>>24; umean += (t3<<24)>>24; vmean += (t3<<16)>>24; umean += (t3<<8)>>24; vmean += t3>>24; umean += 8*128; vmean += 8*128; umean >>= 5; vmean >>= 5; tmp = (vmean<<6) | (umean); uvindx = uvremap[tmp]; } q0 = ((int *)tyy)[0]; q1 = ((int *)tyy)[stride]; q2 = ((int *)tyy)[stride+stride]; q3 = ((int *)tyy)[stride+stride+stride]; ymean = q0 & 0xff; ymean += (q0<<16)>>24; ymean += (q0<<8)>>24; ymean += q0>>24; ymean += q1 & 0xff; ymean += (q1<<16)>>24; ymean += (q1<<8)>>24; ymean += q1>>24; ymean += q2 & 0xff; ymean += (q2<<16)>>24; ymean += (q2<<8)>>24; ymean += q2>>24; ymean += q3 & 0xff; ymean += (q3<<16)>>24; ymean += (q3<<8)>>24; ymean += q3>>24; draft-ietf-avt-cellb-profile-04.txt [Page 11] INTERNET-DRAFT CellB Profile March 1994 /* .... next the bit mask for the tile is generated. for the first fifteen bits this is done by comparing each luminance value to the mean. if that value is greater than the mean the corresponding bit in the mask is set, otherwise the counter for the number of zeros in the mask, tmp, is incremented. This is handled by the SetMaskBit macro. also, the values of those pixels greater than the mean are accumulated in yhi, and the value of those less than the mean are accumulated in ylo .... */ mask = 0; ylo = 0; yhi = 0; tmp = 0; ymean >>= 4; yval = q3 & 255; SetMaskBit(yval, 0); yval = q3 << 16; yval >>= 24; SetMaskBit(yval, 1); yval = q3 << 8; yval >>= 24; SetMaskBit(yval, 2); yval = q3 >> 24; SetMaskBit(yval, 3); yval = q2 & 255; SetMaskBit(yval, 4); yval = q2 << 16; yval >>= 24; SetMaskBit(yval, 5); yval = q2 << 8; yval >>= 24; SetMaskBit(yval, 6); yval = q2 >> 24; SetMaskBit(yval, 7); yval = q1 & 255; SetMaskBit(yval, 8); yval = q1 << 16; yval >>= 24; SetMaskBit(yval, 9); yval = q1 << 8; yval >>= 24; SetMaskBit(yval, 10); draft-ietf-avt-cellb-profile-04.txt [Page 12] INTERNET-DRAFT CellB Profile March 1994 yval = q1 >> 24; SetMaskBit(yval, 11); yval = q0 & 255; SetMaskBit(yval, 12); yval = q0 << 16; yval >>= 24; SetMaskBit(yval, 13); yval = q0 << 8; yval >>= 24; SetMaskBit(yval, 14); yval = q0 >> 24; /* .... the last bit of the bitmask is calculated differently. if this pixel, the one in the upper-left corner is less than the mean, the last bit is calculated more-or-less normally. however, if this last pixel is greater or equal to the mean the mask is complemented and the meaning of ylo and yhi are reversed.... at this point the mean value of the hi and lo pixels are calculated this is accomplished by using the division lookup table. this table is index by the value of the accumulated pixels and the number of pixel contributing to that sum .... */ if (yval < ymean) { ylo += yval; tmp += 1; ylo = divtable[tmp][ylo]; tmp = 16 - tmp; yhi = divtable[tmp][yhi]; ylo <<= 8; } else { yhi += yval; ylo = divtable[tmp][ylo]; tmp = 16 - tmp; yhi = divtable[tmp][yhi]; mask ^= 0x7fff; yhi <<= 8; } /* .... the high mean and low mean values are finally quantized by the yyremap[ ] table, the Y/Y vector codeword byte, the U/V codeword byte and the bitmask are then assembled into a Normal Cell bytecode and returned form the routine .... */ yhi += ylo; draft-ietf-avt-cellb-profile-04.txt [Page 13] INTERNET-DRAFT CellB Profile March 1994 yval = yyremap[yhi]; mask <<= 16; uvindx <<= 8; mask += uvindx; mask += yval; return (mask); } #define CountBits(COUNT, PATTERN) \ COUNT = PATTERN & mask5555; \ PATTERN >>= 1; \ PATTERN &= mask5555; \ COUNT += PATTERN; \ PATTERN = COUNT & mask3333; \ COUNT >>= 2; \ COUNT &= mask3333; \ COUNT += PATTERN; \ PATTERN = COUNT & 0x0f0f; \ COUNT >>= 4; \ COUNT &= 0x0f0f; \ COUNT += PATTERN; \ PATTERN = COUNT & 0xff; \ COUNT >>= 8; \ COUNT += PATTERN u_int32 skip_cell(int index, u_int32 ccell) { /* .... this routine determines if a given cell should be skipped or updated. To start, each cell should be updated approximately once every 8 frames and never less that once in 10 frames. A pseudo-random update strategy has been adopted since it tends to equalize the number of bytes required for each frame, avoiding the a sudden burst of activity every 10 frames for a relatively static image .... Further determination of when a cell should be skipped is done by comparing the current, or update, cell value with the value last transmitted for that cell position .... */ if (cellkount[index] != 0) { u_int32 rmask, rtmp, ctmp; draft-ietf-avt-cellb-profile-04.txt [Page 14] INTERNET-DRAFT CellB Profile March 1994 /* .... grab the UV fields of the reference and current cells, then check if the two fields are "close". this is accomplished with a table called uvlookup[]. this table is actually a bitvector where each bit-position is set or cleared according to whether, UV(old) is close to UV(new), The heuristic for closeness is embodied by the uvclose[ ] vector which in the first version was based on euclidean distances .... */ rmask = cellhistory[index]; rtmp = (rmask << 16) >> 24; ctmp = (ccell << 16) >> 24; rtmp = (rtmp << 5) + (ctmp >> 3); ctmp = ctmp & 7; if ((uvlookup[rtmp] & (1 << ctmp)) != 0) { u_int32 cmask, pattern; int cy0, cy1, ry0, ry1; int bits, diff, count; u_int32 mask5555 = 0x5555; u_int32 mask3333 = 0x3333; /* .... if the colors were close then the total absolute luminance difference between the reference tile and the current tile is calculated ... The Y/Y vectors are first de-quantized, via yytable lookups, and the difference corresponding to each of the possible bitmask differences between the reference mask and the current mask are found and multiplied by the number of occurances of each particular bit patterns. Reference Current Tile Bit Tile Bit 0 0 |ry0 - cy0| 0 1 |ry0 - cy1| 1 0 |ry1 - cy0| 1 1 |ry1 - cy1| The multiplys and absolute value of the luminance differences are performed by a table lookup. the number of bits corresponding to a given condition is computed by the CountBits( ) macro, which returns the value draft-ietf-avt-cellb-profile-04.txt [Page 15] INTERNET-DRAFT CellB Profile March 1994 in "count". Note: that the 0/0 condition is not actually computed but deduced from the number of bits remaining after the 1/1, 0/1, and 1/0 conditions are counted.... */ /* .... de-quantize Y/Y values and get the luminance values .... */ cy0 = ccell & 255; ry0 = rmask & 255; cmask = ccell >> 16; rmask = rmask >> 16; cy0 = yytable[cy0]; ry0 = yytable[ry0]; cy1 = cy0 & 255; ry1 = 256 - (ry0 & 255); cy0 = cy0 >> 8; ry0 = 256 - (ry0 >> 8); bits = 16; /* .... find the 1/1 bits .... */ pattern = cmask & rmask; CountBits(count, pattern); bits -= count; diff = error[count][cy1 + ry1]; /* .... find the 1/0 bits .... */ pattern = cmask & ~rmask; CountBits(count, pattern); bits -= count; diff += error[count][cy1 + ry0]; /* .... find the 0/1 bits .... */ pattern = ~cmask & rmask; CountBits(count, pattern); bits -= count; diff += error[count][cy0 + ry1]; draft-ietf-avt-cellb-profile-04.txt [Page 16] INTERNET-DRAFT CellB Profile March 1994 /* .... add in error from the 0/0 bits .... */ diff += error[bits][cy0 + ry0]; /* .... if the total absolute luminance difference between the reference and the current cell are found to be less than 144 then skip the cell. this value of 144 was determined subjectively. 144 corresponds to an average luminance error of 9 per pixel which in most cases was barely visually noticable, and in typical cases, where the camera position is fixed, the subject is against a static background and occupys approximately 50% of the displayed pixels, this threshold allowed ~80% of all cells to be skipped, with very little observable difference verses sending all cells .... */ if (diff < 144) { cellkount[index] -= 1; return -1; } } } cellhistory[index] = ccell; cellkount[index] = (randbyte( ) & 7) + 13; return 0; } #define STATES 23 static int nextindex = 0; static u_int8 rtable[STATES] = { 146, 75, 3, 95, 189, 165, 106, 229, 239, 14, 208, 90, 8, 222, 122, 236, 200, 171, 225, 131, 94, 12, 74 }; /* .... randbyte( ) does not repeat after 100,000,000 calls .... */ draft-ietf-avt-cellb-profile-04.txt [Page 17] INTERNET-DRAFT CellB Profile March 1994 int randbyte(void) { int i, rval; int *nptr = &nextindex; int next = *nptr; if ((i = next - 1) < 0) i = STATES - 1; rtable[next] = rval = rtable[next] + rtable[i]; if ((next += 1) > (STATES-1)) { *nptr = 0; } else { *nptr = next; } return rval; } draft-ietf-avt-cellb-profile-04.txt [Page 18] INTERNET-DRAFT CellB Profile March 1994 4.2 Sample Decoder The C code included here represents a reference decoder for CellB. For complete source refer to [3]. /* * Copyright (c) Sun Microsystems, Inc. 1992, 1993, 1994. All rights reserved. * * License is granted to copy, to use, and to make and to use derivative * works for research and evaluation purposes, provided that Sun Microsystems is * acknowledged in all documentation pertaining to any such copy or derivative * work. Sun Microsystems grants no other licenses expressed or implied. The * Sun Microsystems trade name should not be used in any advertising without * its written permission. * * This software is provided "as-is" without express or implied warranty of * any kind. These notices must be retained in any copies of any part of * this software. */ #include #include "sized_types.h" #include "video.h" #include "cellb.h" #define ADJUST 128 static uint16 uvtable[252] = { 0x1010, 0x1030, 0x1050, 0x1070, 0x1090, 0x10b0, 0x10d0, 0x10f0, 0x3010, 0x3030, 0x3050, 0x3070, 0x3090, 0x30b0, 0x30d0, 0x30f0, 0x4070, 0x4080, 0x4090, 0x40a0, 0x40b0, 0x5010, 0x5030, 0x5050, 0x5060, 0x5070, 0x5080, 0x5090, 0x50a0, 0x50b0, 0x50c0, 0x50d0, 0x50f0, 0x6050, 0x6060, 0x6070, 0x6080, 0x6090, 0x60a0, 0x60b0, 0x60c0, 0x60d0, 0x6880, 0x6888, 0x6890, 0x6898, 0x68a0, 0x7010, 0x7030, 0x7040, 0x7050, 0x7060, 0x7070, 0x7078, 0x7080, 0x7088, 0x7090, 0x7098, 0x70a0, 0x70a8, 0x70b0, 0x70c0, 0x70d0, 0x70e0, 0x70f0, 0x7870, 0x7878, 0x7880, 0x7888, 0x7890, 0x7898, 0x78a0, 0x78a8, 0x78b0, 0x8040, 0x8050, 0x8060, 0x8068, 0x8070, 0x8078, 0x8080, 0x8088, 0x8090, 0x8098, 0x80a0, 0x80a8, 0x80b0, 0x80b8, 0x80c0, 0x80d0, 0x80e0, 0x8488, 0x848c, 0x8490, 0x8494, 0x8498, 0x8868, 0x8870, 0x8878, 0x8880, 0x8884, 0x8888, 0x888c, 0x8890, 0x8894, 0x8898, 0x889c, 0x88a0, 0x88a8, 0x88b0, 0x88b8, 0x8c84, 0x8c88, 0x8c8c, 0x8c90, 0x8c94, 0x8c98, 0x8c9c, 0x9010, 0x9030, 0x9040, 0x9050, 0x9060, 0x9068, 0x9070, 0x9078, 0x9080, 0x9084, 0x9088, 0x908c, 0x9090, 0x9094, 0x9098, 0x909c, 0x90a0, 0x90a8, 0x90b0, 0x90b8, 0x90c0, 0x90d0, 0x90e0, 0x90f0, 0x9484, 0x9488, 0x948c, 0x9490, 0x9494, 0x9498, 0x949c, 0x9868, 0x9870, 0x9878, 0x9880, 0x9884, 0x9888, 0x988c, 0x9890, 0x9894, 0x9898, 0x989c, draft-ietf-avt-cellb-profile-04.txt [Page 19] INTERNET-DRAFT CellB Profile March 1994 0x98a0, 0x98a8, 0x98b0, 0x98b8, 0x9c88, 0x9c8c, 0x9c90, 0x9c94, 0x9c98, 0xa040, 0xa050, 0xa060, 0xa068, 0xa070, 0xa078, 0xa080, 0xa088, 0xa090, 0xa098, 0xa0a0, 0xa0a8, 0xa0b0, 0xa0b8, 0xa0c0, 0xa0d0, 0xa0e0, 0xa870, 0xa878, 0xa880, 0xa888, 0xa890, 0xa898, 0xa8a0, 0xa8a8, 0xa8b0, 0xb010, 0xb030, 0xb040, 0xb050, 0xb060, 0xb070, 0xb078, 0xb080, 0xb088, 0xb090, 0xb098, 0xb0a0, 0xb0a8, 0xb0b0, 0xb0c0, 0xb0d0, 0xb0e0, 0xb0f0, 0xb880, 0xb888, 0xb890, 0xb898, 0xb8a0, 0xc050, 0xc060, 0xc070, 0xc080, 0xc090, 0xc0a0, 0xc0b0, 0xc0c0, 0xc0d0, 0xd010, 0xd030, 0xd050, 0xd060, 0xd070, 0xd080, 0xd090, 0xd0a0, 0xd0b0, 0xd0c0, 0xd0d0, 0xd0f0, 0xe070, 0xe080, 0xe090, 0xe0a0, 0xe0b0, 0xf010, 0xf030, 0xf050, 0xf070, 0xf090, 0xf0b0, 0xf0d0, 0xf0f0 }; static uint16 yytable[256] = { 0x1014, 0x1018, 0x1020, 0x1030, 0x1040, 0x1050, 0x1070, 0x1090, 0x10b0, 0x10d0, 0x10f0, 0x1418, 0x181c, 0x1820, 0x1828, 0x1c20, 0x2024, 0x2028, 0x2030, 0x2040, 0x2050, 0x2060, 0x2428, 0x282c, 0x2830, 0x2838, 0x2c30, 0x3034, 0x3038, 0x3040, 0x3050, 0x3060, 0x3070, 0x3090, 0x30b0, 0x30d0, 0x30f0, 0x3438, 0x383c, 0x3840, 0x3848, 0x3c40, 0x4044, 0x4048, 0x4050, 0x4060, 0x4070, 0x4080, 0x4448, 0x484c, 0x4850, 0x4858, 0x4c50, 0x5054, 0x5058, 0x5060, 0x5070, 0x5080, 0x5090, 0x50b0, 0x50d0, 0x50f0, 0x5458, 0x585c, 0x5860, 0x5868, 0x5c60, 0x6064, 0x6068, 0x6070, 0x6080, 0x6090, 0x60a0, 0x6468, 0x686c, 0x6870, 0x6878, 0x6c70, 0x7074, 0x7078, 0x7080, 0x7090, 0x70a0, 0x70b0, 0x70d0, 0x70f0, 0x7880, 0x7888, 0x8088, 0x8090, 0x80a0, 0x80b0, 0x80c0, 0x8890, 0x8898, 0x9098, 0x90a0, 0x90b0, 0x90c0, 0x90d0, 0x90f0, 0x98a0, 0x98a8, 0xa0a8, 0xa0b0, 0xa0c0, 0xa0d0, 0xa0e0, 0xa8b0, 0xa8b8, 0xb0b8, 0xb0c0, 0xb0d0, 0xb0e0, 0xb0f0, 0xb8c0, 0xb8c8, 0xc0c8, 0xc0d0, 0xc0e0, 0xc0f0, 0xc8d0, 0xc8d8, 0xd0d8, 0xd0e0, 0xd0f0, 0xd8e8, 0xe0f0, 0x1410, 0x1810, 0x2010, 0x3010, 0x4010, 0x5010, 0x7010, 0x9010, 0xb010, 0xd010, 0xf010, 0x1814, 0x1c18, 0x2018, 0x2818, 0x201c, 0x2420, 0x2820, 0x3020, 0x4020, 0x5020, 0x6020, 0x2824, 0x2c28, 0x3028, 0x3828, 0x302c, 0x3430, 0x3830, 0x4030, 0x5030, 0x6030, 0x7030, 0x9030, 0xb030, 0xd030, 0xf030, 0x3834, 0x3c38, 0x4038, 0x4838, 0x403c, 0x4440, 0x4840, 0x5040, 0x6040, 0x7040, 0x8040, 0x4844, 0x4c48, 0x5048, 0x5848, 0x504c, 0x5450, 0x5850, 0x6050, 0x7050, 0x8050, 0x9050, 0xb050, 0xd050, 0xf050, 0x5854, 0x5c58, 0x6058, 0x6858, 0x605c, 0x6460, 0x6860, 0x7060, 0x8060, 0x9060, 0xa060, 0x6864, 0x6c68, 0x7068, 0x7868, 0x706c, 0x7470, 0x7870, 0x8070, 0x9070, 0xa070, 0xb070, 0xd070, 0xf070, 0x8078, 0x8878, 0x8880, 0x9080, 0xa080, 0xb080, 0xc080, 0x9088, 0x9888, 0x9890, 0xa090, 0xb090, 0xc090, 0xd090, 0xf090, 0xa098, 0xa898, 0xa8a0, 0xb0a0, 0xc0a0, 0xd0a0, 0xe0a0, 0xb0a8, 0xb8a8, 0xb8b0, 0xc0b0, 0xd0b0, 0xe0b0, 0xf0b0, 0xc0b8, 0xc8b8, 0xc8c0, 0xd0c0, 0xe0c0, 0xf0c0, 0xd0c8, 0xd8c8, 0xd8d0, 0xe0d0, 0xf0d0, 0xe8d8, 0xf0e0 }; draft-ietf-avt-cellb-profile-04.txt [Page 20] INTERNET-DRAFT CellB Profile March 1994 int CellB_Decode(vidimage_t *image, uint8 *data, int len) { int orig_cellx, orig_celly, cellx, celly, width, offset; int pattern, yyindx, uvindx; uint32 *yorigin, *uvorigin, *yptr, *uvptr, yout, uvout; uint8 *dataLim=data+len, y1, y2, uu, vv; width = image->width / 4; if (dataLim-data < 8) return 1; /* Get cell x, y location */ orig_cellx = cellx = (data[0] << 8) + data[1]; orig_celly = celly = (data[2] << 8) + data[3]; data += 4; /* Skip over width and height. */ data += 4; yorigin = (uint32 *) image->y_data; uvorigin = (uint32 *) image->uv_data; while (data < dataLim) { pattern = *data; if (pattern >= 128) { cellx += (pattern-127); while (cellx >= width) { cellx -= width; celly++; } data++; } else { if (dataLim-data < 4) return 1; pattern = (pattern << 8) + data[1]; uvindx = data[2]; yyindx = data[3]; y1 = (uint8)(yytable[yyindx] >> 8); y2 = (uint8)(yytable[yyindx] & 0xff); uu = (uint8)((uvtable[uvindx] >> 8) ^ ADJUST); vv = (uint8)((uvtable[uvindx] & 0xff) ^ ADJUST); offset = celly*4*width + cellx; yptr = &yorigin[offset]; uvptr = &uvorigin[offset]; draft-ietf-avt-cellb-profile-04.txt [Page 21] INTERNET-DRAFT CellB Profile March 1994 yout = (pattern & 0x8000) ? y2 : y1; yout = (yout << 8) + ((pattern & 0x4000) ? y2 : y1); yout = (yout << 8) + ((pattern & 0x2000) ? y2 : y1); yout = (yout << 8) + ((pattern & 0x1000) ? y2 : y1); yptr[0] = yout; yout = (pattern & 0x0800) ? y2 : y1; yout = (yout << 8) + ((pattern & 0x0400) ? y2 : y1); yout = (yout << 8) + ((pattern & 0x0200) ? y2 : y1); yout = (yout << 8) + ((pattern & 0x0100) ? y2 : y1); yptr[width] = yout; yptr += 2*width; yout = (pattern & 0x0080) ? y2 : y1; yout = (yout << 8) + ((pattern & 0x0040) ? y2 : y1); yout = (yout << 8) + ((pattern & 0x0020) ? y2 : y1); yout = (yout << 8) + ((pattern & 0x0010) ? y2 : y1); yptr[0] = yout; yout = (pattern & 0x0008) ? y2 : y1; yout = (yout << 8) + ((pattern & 0x0004) ? y2 : y1); yout = (yout << 8) + ((pattern & 0x0002) ? y2 : y1); yout = (yout << 8) + ((pattern & 0x0001) ? y2 : y1); yptr[width] = yout; uvout = (uu << 24) + (vv << 16) + (uu << 8) + vv; uvptr[0] = uvptr[width] = uvout; uvptr += 2*width; uvptr[0] = uvptr[width] = uvout; cellx++; if (cellx >= width) { cellx -= width; celly++; } data += 4; } } if (cellx == 0) celly--; return (0); } draft-ietf-avt-cellb-profile-04.txt [Page 22] INTERNET-DRAFT CellB Profile March 1994 5 References 1. "Cell Image Compression Byte Stream Description," Available via anonymous ftp: playground.sun.com:/pub/multimedia/video. 2. Henning Schulzrinne, Stephen Casner "RTP: A Transport Protocol for Real-Time Applications," Internet Draft, March 21st, 1995 3. Nv Video Compression Software, Unpublished work by Ron Frederick, Xerox PARC. 4. Thierry Turletti, Christian Huitema INRIA, "RTP Packetization of H.261 Video Streams, Internet Draft, March 8th, 1995. 6 Address of the Authors Michael F. Speer Sun Microsystems Computer Corporation 2550 Garcia Ave MailStop UMPK14-305 Mountain View, CA 94043 Voice: +1 415 786 6368 Fax: +1 415 786 6445 E-mail: michael.speer@eng.sun.com Don Hoffman Sun Microsystems Computer Corporation 2550 Garcia Ave MailStop UMPK14-305 Mountain View, CA 94043 Voice: +1 415 786 6370 Fax: +1 415 786 6445 E-mail: don.hoffman@eng.sun.com draft-ietf-avt-cellb-profile-04.txt [Page 23]