1e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen/*
2e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Copyright (C) 2011 The Android Open Source Project
3e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *
4e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Licensed under the Apache License, Version 2.0 (the "License");
5e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * you may not use this file except in compliance with the License.
6e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * You may obtain a copy of the License at
7e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *
8e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *      http://www.apache.org/licenses/LICENSE-2.0
9e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *
10e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Unless required by applicable law or agreed to in writing, software
11e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * distributed under the License is distributed on an "AS IS" BASIS,
12e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * See the License for the specific language governing permissions and
14e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * limitations under the License.
15e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */
16e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
17e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen///////////////////////////////////////////////////
18e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// Mosaic.pp
19e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// S.O. # :
20e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// Author(s): zkira
21e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// $Id: Mosaic.cpp,v 1.20 2011/06/24 04:22:14 mbansal Exp $
22e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
23e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <stdio.h>
24e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <string.h>
25e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
26e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "Mosaic.h"
27e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "trsMatrix.h"
28e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
29274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#include "Log.h"
30274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#define LOG_TAG "MOSAIC"
31274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen
32e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenMosaic::Mosaic()
33e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
34e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    initialized = false;
35e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    imageMosaicYVU = NULL;
36e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    frames_size = 0;
37e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    max_frames = 200;
38e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
39e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
40e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenMosaic::~Mosaic()
41e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
42e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int i = 0; i < frames_size; i++)
43e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
44e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (frames[i])
45e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            delete frames[i];
46e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
47e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    delete frames;
48b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    delete rframes;
49e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
50e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (aligner != NULL)
51e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        delete aligner;
52e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (blender != NULL)
53e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        delete blender;
54e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
55e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
56b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansalint Mosaic::initialize(int blendingType, int stripType, int width, int height, int nframes, bool quarter_res, float thresh_still)
57e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
58e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    this->blendingType = blendingType;
59b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal
60b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    // TODO: Review this logic if enabling FULL or PAN mode
61b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    if (blendingType == Blend::BLEND_TYPE_FULL ||
62b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal            blendingType == Blend::BLEND_TYPE_PAN)
63b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    {
64b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal        stripType = Blend::STRIP_TYPE_THIN;
65b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    }
66b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal
67b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    this->stripType = stripType;
68e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    this->width = width;
69e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    this->height = height;
70e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
71b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal
72e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    mosaicWidth = mosaicHeight = 0;
73e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    imageMosaicYVU = NULL;
74e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
75e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    frames = new MosaicFrame *[max_frames];
76b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    rframes = new MosaicFrame *[max_frames];
77e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
78e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if(nframes>-1)
79e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
80e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        for(int i=0; i<nframes; i++)
81e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
82e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            frames[i] = new MosaicFrame(this->width,this->height,false); // Do no allocate memory for YUV data
83e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
84e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
85e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else
86e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
87e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        for(int i=0; i<max_frames; i++)
88e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
89e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            frames[i] = NULL;
90e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
91e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
92e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
93e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
94e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
95274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    LOGV("Initialize %d %d", width, height);
96274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    LOGV("Frame width %d,%d", width, height);
97274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    LOGV("Max num frames %d", max_frames);
98e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
99274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    aligner = new Align();
100274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    aligner->initialize(width, height,quarter_res,thresh_still);
101e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
102e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (blendingType == Blend::BLEND_TYPE_FULL ||
103e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            blendingType == Blend::BLEND_TYPE_PAN ||
104e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            blendingType == Blend::BLEND_TYPE_CYLPAN ||
105e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            blendingType == Blend::BLEND_TYPE_HORZ) {
106e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        blender = new Blend();
107b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal        blender->initialize(blendingType, stripType, width, height);
108e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    } else {
109e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        blender = NULL;
110274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen        LOGE("Error: Unknown blending type %d",blendingType);
111e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        return MOSAIC_RET_ERROR;
112e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
113e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
114e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    initialized = true;
115e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
116e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return MOSAIC_RET_OK;
117e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
118e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
119e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Mosaic::addFrameRGB(ImageType imageRGB)
120e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
121e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageType imageYVU;
122e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Convert to YVU24 which is used by blending
123e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    imageYVU = ImageUtils::allocateImage(this->width, this->height, ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
124e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageUtils::rgb2yvu(imageYVU, imageRGB, width, height);
125e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
126e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return addFrame(imageYVU);
127e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
128e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
129e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Mosaic::addFrame(ImageType imageYVU)
130e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
131e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if(frames[frames_size]==NULL)
132e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        frames[frames_size] = new MosaicFrame(this->width,this->height,false);
133e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
134e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    MosaicFrame *frame = frames[frames_size];
135e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
136e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    frame->image = imageYVU;
137e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
138e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Add frame to aligner
139dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    int ret = MOSAIC_RET_ERROR;
140e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (aligner != NULL)
141e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
142e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        // Note aligner takes in RGB images
143dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        int align_flag = Align::ALIGN_RET_OK;
144e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        align_flag = aligner->addFrame(frame->image);
145e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        aligner->getLastTRS(frame->trs);
146e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
147e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (frames_size >= max_frames)
148e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
149dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            LOGV("WARNING: More frames than preallocated, ignoring."
150dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                 "Increase maximum number of frames (-f <max_frames>) to avoid this");
151e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            return MOSAIC_RET_ERROR;
152e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
153dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
154dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        switch (align_flag)
155e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
156dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            case Align::ALIGN_RET_OK:
157dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                frames_size++;
158dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                ret = MOSAIC_RET_OK;
159dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                break;
160dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            case Align::ALIGN_RET_FEW_INLIERS:
161dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                frames_size++;
162dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                ret = MOSAIC_RET_FEW_INLIERS;
163dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                break;
164dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            case Align::ALIGN_RET_LOW_TEXTURE:
165dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                ret = MOSAIC_RET_LOW_TEXTURE;
166dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                break;
167dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            case Align::ALIGN_RET_ERROR:
168dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                ret = MOSAIC_RET_ERROR;
169dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                break;
170dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            default:
171dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                break;
172e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
173e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
174dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
175dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    return ret;
176e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
177e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
178e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
179e1178a73fd5756771d25d0b8375452450f509e99mbansalint Mosaic::createMosaic(float &progress, bool &cancelComputation)
180e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
18150f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen    if (frames_size <= 0)
18250f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen    {
18350f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen        // Haven't accepted any frame in aligner. No need to do blending.
18450f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen        progress = TIME_PERCENT_ALIGN + TIME_PERCENT_BLEND
18550f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen                + TIME_PERCENT_FINAL;
18650f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen        return MOSAIC_RET_OK;
18750f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen    }
18850f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen
189e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (blendingType == Blend::BLEND_TYPE_PAN)
190e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
191e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
192e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        balanceRotations();
193e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
194e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
195e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
196274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    int ret = Blend::BLEND_RET_ERROR;
197e1178a73fd5756771d25d0b8375452450f509e99mbansal
198e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Blend the mosaic (alignment has already been done)
199e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (blender != NULL)
200e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
201b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal        ret = blender->runBlend((MosaicFrame **) frames, (MosaicFrame **) rframes,
202b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal                frames_size, imageMosaicYVU,
203e1178a73fd5756771d25d0b8375452450f509e99mbansal                mosaicWidth, mosaicHeight, progress, cancelComputation);
204e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
205e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
206e1178a73fd5756771d25d0b8375452450f509e99mbansal    switch(ret)
207e1178a73fd5756771d25d0b8375452450f509e99mbansal    {
208e1178a73fd5756771d25d0b8375452450f509e99mbansal        case Blend::BLEND_RET_ERROR:
209e1178a73fd5756771d25d0b8375452450f509e99mbansal        case Blend::BLEND_RET_ERROR_MEMORY:
210e1178a73fd5756771d25d0b8375452450f509e99mbansal            ret = MOSAIC_RET_ERROR;
211e1178a73fd5756771d25d0b8375452450f509e99mbansal            break;
212e1178a73fd5756771d25d0b8375452450f509e99mbansal        case Blend::BLEND_RET_CANCELLED:
213e1178a73fd5756771d25d0b8375452450f509e99mbansal            ret = MOSAIC_RET_CANCELLED;
214e1178a73fd5756771d25d0b8375452450f509e99mbansal            break;
215e1178a73fd5756771d25d0b8375452450f509e99mbansal        case Blend::BLEND_RET_OK:
216e1178a73fd5756771d25d0b8375452450f509e99mbansal            ret = MOSAIC_RET_OK;
217e1178a73fd5756771d25d0b8375452450f509e99mbansal    }
218e1178a73fd5756771d25d0b8375452450f509e99mbansal    return ret;
219e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
220e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
221e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenImageType Mosaic::getMosaic(int &width, int &height)
222e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
223e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    width = mosaicWidth;
224e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    height = mosaicHeight;
225e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
226e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return imageMosaicYVU;
227e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
228e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
229e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
230e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
231e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Mosaic::balanceRotations()
232e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
233e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Normalize to the mean angle of rotation (Smiley face)
234e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double sineAngle = 0.0;
235e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
236e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int i = 0; i < frames_size; i++) sineAngle += frames[i]->trs[0][1];
237e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    sineAngle /= frames_size;
238e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Calculate the cosineAngle (1 - sineAngle*sineAngle) = cosineAngle*cosineAngle
239e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double cosineAngle = sqrt(1.0 - sineAngle*sineAngle);
240e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double m[3][3] = {
241e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        { cosineAngle, -sineAngle, 0 },
242e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        { sineAngle, cosineAngle, 0},
243e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        { 0, 0, 1}};
244e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double tmp[3][3];
245e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
246e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int i = 0; i < frames_size; i++) {
247e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        memcpy(tmp, frames[i]->trs, sizeof(tmp));
248e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mult33d(frames[i]->trs, m, tmp);
249e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
250e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
251e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return MOSAIC_RET_OK;
252e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
253