function [frame_encoded, varargout] =...
    encode_frame(frame_in, B_size, MB_size, Q, type, varargin)

switch type
    case 'P'
        ref = varargin{1};
        search_width = varargin{2};
        block_matching = varargin{3};
        mp_resolution = varargin{4};
        
    case 'B'
        ref_forw = varargin{1};
        ref_back = varargin{2};
        search_width = varargin{3};
        block_matching = varargin{4};
        mp_resolution = varargin{5};
end

[Y,chroma] = RGB_to_YCbCr(frame_in);
switch type
    case 'P'
        [Y_ref, chroma_ref] = RGB_to_YCbCr(ref);
    case 'B'
        [Y_ref_f, chroma_ref_f] = RGB_to_YCbCr(ref_forw);
        [Y_ref_b, chroma_ref_b] = RGB_to_YCbCr(ref_back);
end

Nmb = size(Y)/MB_size;

Y_mb = mat2cell(Y, repmat(MB_size,1,Nmb(1)), repmat(MB_size,1,Nmb(2)));
Y_encoded = cell(size(Y_mb));

chroma_mb = mat2cell(chroma, repmat(MB_size/2,1,Nmb(1)), repmat(MB_size/2,1,Nmb(2)),2);
chroma_encoded = cell(size(chroma_mb));

switch type
    case 'P'
        u = zeros(size(Y_mb));
        v = zeros(size(Y_mb));
    case 'B'
        u_f = zeros(size(Y_mb));
        v_f = zeros(size(Y_mb));
        u_b = zeros(size(Y_mb));
        v_b = zeros(size(Y_mb));
end

for n = 1 : Nmb(1)
    for m = 1 : Nmb(2)
        switch type
            case 'I'
                srcY = Y_mb{n,m};
                srcC = chroma_mb{n,m};
            case 'P'
                [u(n,m), v(n,m)]  = get_motion_vector( Y_mb{n,m}, n, m, Y_ref, MB_size, search_width, block_matching,mp_resolution );
                srcY = motion_prediction( Y_mb{n,m}, Y_ref, u(n,m), v(n,m), n, m, mp_resolution );
                srcC = motion_prediction( chroma_mb{n,m}, chroma_ref, u(n,m), v(n,m), n, m, mp_resolution);
            case 'B'
                [u_f(n,m), v_f(n,m)]  = get_motion_vector( Y_mb{n,m}, n, m, Y_ref_f, MB_size, search_width, block_matching,mp_resolution);
                [u_b(n,m), v_b(n,m)]  = get_motion_vector( Y_mb{n,m}, n, m, Y_ref_b, MB_size, search_width, block_matching,mp_resolution);
                Y_forw_pred = motion_prediction( Y_mb{n,m}, Y_ref_f, u_f(n,m), v_f(n,m), n, m,mp_resolution );
                Y_back_pred = motion_prediction( Y_mb{n,m}, Y_ref_b, u_b(n,m), v_b(n,m), n, m,mp_resolution );
                chroma_forw_pred = motion_prediction( chroma_mb{n,m}, chroma_ref_f, u_f(n,m), v_f(n,m), n, m,mp_resolution );
                chroma_back_pred = motion_prediction( chroma_mb{n,m}, chroma_ref_b, u_b(n,m), v_b(n,m), n, m,mp_resolution );
                srcY = (Y_forw_pred+Y_back_pred)/2;
                srcC = (chroma_forw_pred+chroma_back_pred)/2;
        end
        Y_encoded{n,m} =  quantize(  srcY , B_size, Q );
        chroma_encoded{n,m} =  quantize(  srcC , B_size, Q );
    end
end

Y_encoded = cell2mat(Y_encoded);
chroma_encoded = cell2mat(chroma_encoded);
frame_encoded = struct('encoded_luma',Y_encoded,'encoded_chroma',chroma_encoded);

switch type
    case 'P'
        varargout{1} = u;
        varargout{2} = v;
    case 'B'
        varargout{1} = u_f;
        varargout{2} = v_f;
        varargout{3} = u_b;
        varargout{4} = v_b;
end

end
