-- M module extracted from ITU-T J.249 (01/2010)
function [si_orig, part_si_min, part_si_max, ... hv_feat_orig, part_hv_min, part_hv_max, y_orig, ... cb_orig, cr_orig, part_c_min, part_c_max, part_c, ... ati_orig, part_ati_min, part_ati_max, part_ati, code_ati ] ... = model_lowbw_compression (mode, transmit_file, si_orig, hv_feat_orig, luma_orig, cb_orig, cr_orig, ati_orig); % MODEL_LOWBW_COMPRESSION % Compress and write original features from the LowBW or FastLowBW model. % Alternatively reverse that process: read and uncompress features. % SYNTAX % model_lowbw_compression ('compress', transmit_file, si_orig, hv_feat_orig, ... % luma_orig, cb_orig, cr_orig, ati_orig ); % [si_orig, part_si_min, part_si_max, ... % hv_feat_orig, part_hv_min, part_hv_max, y_orig, ... % cb_orig, cr_orig, part_c_min, part_c_max, part_c, ... % ati_orig, part_ati_min, part_ati_max, part_ati, code_ati ] = ... % model_lowbw_compression('uncompress', transmit_file); % DESCRIPTION % When the first argument is 'compress', this function compresses the % features associated with the lowbw model or fastlowbw model, and write % them to a file for transmission. Operates on 255 seconds or less. Longer % sequencesmust be split and written to two different files. To % understand the input arguments, see function model_lowbw_features or % model_fastlowbw_features. % % When the first argument is 'uncompress', this function reverses the % process: reads compressed original features from file 'transmit_file' % and returns those values on the command line. This function also % returns information about the feature compression, which will be needed % by function model_lowbw_parameters.m and model_fastlowbw_parameters.m % To properly understand those parameters (i.e., everything returned that % isn't mentioned in the 'compress' argument list), examine the code % below. if strcmpi(mode,'compress'), [row_si,col_si,time_si] = size(si_orig); [row_cb,col_cb,time_cb] = size(cb_orig); [si_orig] = model_lowbw_compression_internal (si_orig, 'si', 'compress'); [hv_feat_orig] = model_lowbw_compression_internal (hv_feat_orig, 'hv', 'compress'); [luma_orig] = model_lowbw_compression_internal (luma_orig, 'y', 'compress'); [cb_orig] = model_lowbw_compression_internal (cb_orig, 'cb', 'compress'); [cr_orig] = model_lowbw_compression_internal (cr_orig, 'cr', 'compress'); [ati_orig] = model_lowbw_compression_internal (ati_orig, 'ati', 'compress'); if time_si > 255 | time_cb > 255, error('Time sequence too long. Split into shorter segments'); end % save data to file if exist(transmit_file,'file'), delete(transmit_file); end fid = fopen(transmit_file, 'w'); % write overhead for SI & HV & Luma row_si = uint8(row_si); col_si = uint8(col_si); time_si= uint8(time_si); fwrite(fid,row_si,'uint8'); fwrite(fid,col_si,'uint8'); fwrite(fid,time_si,'uint8'); % write out SI & HV & Luma fwrite(fid,si_orig, 'ubit9'); fwrite(fid,hv_feat_orig,'ubit9'); fwrite(fid,luma_orig, 'ubit8'); % write Cb & Cr fwrite(fid,cb_orig, 'ubit9'); fwrite(fid,cr_orig, 'ubit9'); % write overhead for ATI frames = length(ati_orig); fwrite(fid,frames,'ushort'); % write ATI fwrite(fid,ati_orig, 'ubit10'); % fprintf('Total bytes written: %d Sequence Size: (%d,%d,%d) ==> %f kbits/s\n', ftell(fid), ... % row_si,col_si,time_si, (ftell(fid) * 8.0) / (double(time_si) * 1000.0)); fclose(fid); elseif strcmpi(mode,'uncompress'), % load original features if ~exist(transmit_file,'file'), error(sprintf('Cannot open file ''%s'', file does not exist', transmit_file)); end fid = fopen(transmit_file, 'r'); % read overhead for SI & HV & Luma row = fread(fid,1, 'uint8'); col = fread(fid,1,'uint8'); time = fread(fid,1,'uint8'); % read Si & HV & Luma si_orig = fread(fid,row*col*time, 'ubit9'); hv_feat_orig = fread(fid,row*col*time,'ubit9'); y_orig = fread(fid,row*col*time, 'ubit8'); % decompress original features [si_orig, part_si_min, part_si_max] = ... model_lowbw_compression_internal (si_orig, 'si', 'decompress', row,col,time); [hv_feat_orig, part_hv_min, part_hv_max] = ... model_lowbw_compression_internal (hv_feat_orig, 'hv', 'decompress',row,col,time); [y_orig] = model_lowbw_compression_internal (y_orig, 'y', 'decompress',row,col,time); % read Cb & Cr cb_orig = fread(fid,row*col*time, 'ubit9'); cr_orig = fread(fid,row*col*time, 'ubit9'); % decompress original features [cb_orig] = model_lowbw_compression_internal (cb_orig, 'cb', 'decompress',row,col,time); [cr_orig, part_c_min, part_c_max, part_c] = ... model_lowbw_compression_internal (cr_orig, 'cr', 'decompress',row,col,time); % read overhead for ATI & read ATI frames = fread(fid,1,'ushort'); ati_orig = fread(fid,frames, 'ubit10'); % decompress original features [ati_orig, part_ati_min, part_ati_max, part_ati, code_ati] = model_lowbw_compression_internal (ati_orig, 'ati', 'decompress',1,1,frames); fclose(fid); else error('mode not recognized'); end function [data, part_min, part_max, part, code] = ... model_lowbw_compression_internal (feature, type, flag, row, col, time); % model_lowbw_compression_internal % Compress or decompress the lowbw/sec model features. % SYNTAX % [data] = model_lowbw_compression_internal (feature, type, 'compress'); % [data, part_min, part_max, part, code] = ... % model_lowbw_compression_internal (feature, type, 'decompress', row, col, time); % DESCRIPTION % Compress or decompress the features in matrix 'feature'. Variable % 'type' controls the compression (e.g., 'hv', 'si','y','cb', 'cr', or 'ati). % 'flag' should be set to either 'compress' or 'decompress' or 'none'. % ('none' is no compression; return data as-is for saving.) % % Return the compressed or decompressed data in [data]. On % decompression, also return the minimum & maximum partition boundaries % in 'part_min' and 'part_max'. On compression, [data] will be a one % dimensional array. On decompression, [data] will be of size % (row,col,time). % % return value 'part' is the partitions; 'code' is the code values % get quantizer codebook if strcmpi(type,'hv'), [part,code] = model_lowbw_compression_internal_hv; elseif strcmpi(type,'si'), [part,code] = model_lowbw_compression_internal_si; elseif strcmpi(type,'y'), [part,code] = model_lowbw_compression_internal_y; elseif strcmpi(type,'cb') | strcmp(type,'cr'), [part,code] = model_lowbw_compression_internal_cb_cr; elseif strcmpi(type,'ati'), [part,code] = model_lowbw_compression_internal_ati; end if strcmpi(type,'none'), data = feature; return; elseif strcmpi(flag,'compress'), % convert from 3D to 1D [frows,fcols,ftime] = size(feature); feature = reshape(feature,1,frows*fcols*ftime); % row vector for quantizer % Quantize feature [index] = quantiz_fast(feature,part); data = index; return; elseif strcmpi(flag,'decompress'), part_min = part(1); part_max = part( length(part) ); % convert back from indicies to quantized values feature = code(feature+1); data = reshape(feature,row,col,time); return; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [part_hv,code_hv] = model_lowbw_compression_internal_hv; % hv_feat_orig quantizer, 9 bit design % Use a quantizer whose distance between bins (dx) increases as a constant % (err) times the code value. Only preserve this relationship until the % code value decreases to some low value, then uniformly quantize the % remainder. Start at 1.0 so the code is exact there. % First bin will be values less than part_hv(1) and last bin will be % values greater than part_hv(code_hv_size-1). hv_loss and hv_gain parameter values % whose hv_feat_orig values fall outside of the quantizer range will be % zeroed. start = 1.0; err = 0.00709; % fraction of error in the quantized value high_codes = 228; % number of nonlinear codes >= 1.0 low_codes = 202; % number of nonlinear codes < 1.0 vlow_codes = 82; % number of uniform codes for very low values code_hv = [start]; % Generate high codes for i = 1:high_codes-1 code_hv = [code_hv code_hv(i)*(1+err)]; end % Generate low codes for i = 1:low_codes code_hv = [code_hv(1)*(1-err) code_hv]; end % Generate very low codes, uniformly distributed to lowest_code lowest_code = 0.0991; temp = code_hv(1):(lowest_code-1*code_hv(1))/vlow_codes:lowest_code; code_hv = [fliplr(temp(2:vlow_codes+1)) code_hv]; % Generate the partitions, halfway between codes code_hv_size = size(code_hv,2); part_hv = (code_hv(2:code_hv_size)+code_hv(1:code_hv_size-1))/2; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [part_si,code_si] = model_lowbw_compression_internal_si; % si_orig quantizer, 9 bit design % Use a quantizer whose distance between bins (dx) increases as a constant % (err) times the code value. % First bin will be values less than part_si(1) and last bin will be % values greater than part_si(code_si_size-1). si_loss and si_gain parameter values % whose si_orig values fall outside of the quantizer range will be % zeroed. start = 2.99; err = 0.00728; % fraction of error in the quantized value high_codes = 512; % number of nonlinear codes code_si = [start]; % Generate high codes for i = 1:high_codes-1 code_si = [code_si code_si(i)*(1+err)]; end % Generate the partitions, halfway between codes code_si_size = size(code_si,2); part_si = (code_si(2:code_si_size)+code_si(1:code_si_size-1))/2; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [part_y, code_y] = model_lowbw_compression_internal_y; % For y quantizer, just use uniform 8 bit quantizer where the value % represents the y level (0 to 255). Only one byte per % macroblock(3,3,2). start = 0.0; err = 1.00; % distance between codes high_codes = 256; % number of codes code_y = [start]; % Generate high codes for i = 1:high_codes-1 code_y = [code_y code_y(i)+err]; end % Generate the partitions, halfway between codes code_y_size = size(code_y,2); part_y = (code_y(2:code_y_size)+code_y(1:code_y_size-1))/2; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [part_c, code_c] = model_lowbw_compression_internal_cb_cr; % Non-linear quantizer for cb_orig and cr_orig, similar to hv but bipolar (two sided), % since the cb and cr features are bipolar. start = 1.0; err = 0.0216; % fraction of error in the quantized value high_codes = 217; % number of nonlinear codes >= start low_codes = 40; % number of uniform codes for very low values (< start) code_c = [start]; % Generate high codes for i = 1:high_codes-1 code_c = [code_c code_c(i)*(1+err)]; end % Generate low codes, uniformly distributed from lowest_code to start lowest_code = 0.136; temp = code_c(1):(lowest_code-1*code_c(1))/low_codes:lowest_code; code_c = [fliplr(temp(2:low_codes+1)) code_c]; % zero first code and generate sym neg codes code_c(1) = 0.0; code_c = [-1.0*fliplr(code_c(2:(high_codes+low_codes-1))) code_c]; % Generate the partitions, halfway between codes code_c_size = size(code_c,2); part_c = (code_c(2:code_c_size)+code_c(1:code_c_size-1))/2; % Correct partition around zero low_part_spacing = (start-lowest_code)/low_codes; part_c(code_c_size/2) = part_c(code_c_size/2 + 1) - low_part_spacing; part_c(code_c_size/2 - 1) = part_c(code_c_size/2 - 2) + low_part_spacing; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [part_ati, code_ati] = model_lowbw_compression_internal_ati; % ati_orig quantizer, 10 bit design, uniform quantizer design % First bin will be values less than part_ati(1) and last bin will be % values greater than part_ati(code_ati_size-1). start = 0.0; % first code last = 220.0; % 210 is the maximum observed in the training data high_codes = 1024; % number of codes for 10-bit quantizer code_ati = start:(last-start)/(high_codes-1):last; % Generate the partitions, halfway between codes code_ati_size = size(code_ati,2); part_ati = (code_ati(2:code_ati_size)+code_ati(1:code_ati_size-1))/2;