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
500e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei    for (int j = 0; j < owned_size; j++)
510e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei        delete owned_frames[j];
520e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei    delete owned_frames;
530e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei
54e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (aligner != NULL)
55e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        delete aligner;
56e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (blender != NULL)
57e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        delete blender;
58e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
59e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
60b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansalint Mosaic::initialize(int blendingType, int stripType, int width, int height, int nframes, bool quarter_res, float thresh_still)
61e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
62e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    this->blendingType = blendingType;
63b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal
64b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    // TODO: Review this logic if enabling FULL or PAN mode
65b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    if (blendingType == Blend::BLEND_TYPE_FULL ||
66b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal            blendingType == Blend::BLEND_TYPE_PAN)
67b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    {
68b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal        stripType = Blend::STRIP_TYPE_THIN;
69b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    }
70b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal
71b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    this->stripType = stripType;
72e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    this->width = width;
73e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    this->height = height;
74e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
75b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal
76e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    mosaicWidth = mosaicHeight = 0;
77e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    imageMosaicYVU = NULL;
78e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
79e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    frames = new MosaicFrame *[max_frames];
80b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal    rframes = new MosaicFrame *[max_frames];
81e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
82e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if(nframes>-1)
83e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
84e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        for(int i=0; i<nframes; i++)
85e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
86e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            frames[i] = new MosaicFrame(this->width,this->height,false); // Do no allocate memory for YUV data
87e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
88e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
89e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    else
90e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
91e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        for(int i=0; i<max_frames; i++)
92e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
93e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            frames[i] = NULL;
94e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
95e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
96e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
970e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei    owned_frames = new ImageType[max_frames];
980e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei    owned_size = 0;
990e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei
100274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    LOGV("Initialize %d %d", width, height);
101274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    LOGV("Frame width %d,%d", width, height);
102274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    LOGV("Max num frames %d", max_frames);
103e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
104274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    aligner = new Align();
105274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    aligner->initialize(width, height,quarter_res,thresh_still);
106e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
107e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (blendingType == Blend::BLEND_TYPE_FULL ||
108e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            blendingType == Blend::BLEND_TYPE_PAN ||
109e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            blendingType == Blend::BLEND_TYPE_CYLPAN ||
110e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            blendingType == Blend::BLEND_TYPE_HORZ) {
111e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        blender = new Blend();
112b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal        blender->initialize(blendingType, stripType, width, height);
113e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    } else {
114e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        blender = NULL;
115274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen        LOGE("Error: Unknown blending type %d",blendingType);
116e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        return MOSAIC_RET_ERROR;
117e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
118e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
119e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    initialized = true;
120e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
121e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return MOSAIC_RET_OK;
122e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
123e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
124e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Mosaic::addFrameRGB(ImageType imageRGB)
125e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
126e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageType imageYVU;
127e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Convert to YVU24 which is used by blending
128e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    imageYVU = ImageUtils::allocateImage(this->width, this->height, ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
129e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageUtils::rgb2yvu(imageYVU, imageRGB, width, height);
130e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
1310e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei    int existing_frames_size = frames_size;
1320e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei    int ret = addFrame(imageYVU);
1330e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei
1340e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei    if (frames_size > existing_frames_size)
1350e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei        owned_frames[owned_size++] = imageYVU;
1360e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei    else
1370e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei        ImageUtils::freeImage(imageYVU);
1380e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei
1390e4815a5b307a1dc02648616b22f2dc534472180Guozhi Wei    return ret;
140e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
141e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
142e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Mosaic::addFrame(ImageType imageYVU)
143e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
144e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if(frames[frames_size]==NULL)
145e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        frames[frames_size] = new MosaicFrame(this->width,this->height,false);
146e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
147e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    MosaicFrame *frame = frames[frames_size];
148e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
149e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    frame->image = imageYVU;
150e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
151e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Add frame to aligner
152dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    int ret = MOSAIC_RET_ERROR;
153e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (aligner != NULL)
154e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
155e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        // Note aligner takes in RGB images
156dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        int align_flag = Align::ALIGN_RET_OK;
157e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        align_flag = aligner->addFrame(frame->image);
158e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        aligner->getLastTRS(frame->trs);
159e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
160e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        if (frames_size >= max_frames)
161e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
162dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            LOGV("WARNING: More frames than preallocated, ignoring."
163dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                 "Increase maximum number of frames (-f <max_frames>) to avoid this");
164e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen            return MOSAIC_RET_ERROR;
165e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
166dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
167dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        switch (align_flag)
168e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        {
169dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            case Align::ALIGN_RET_OK:
170dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                frames_size++;
171dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                ret = MOSAIC_RET_OK;
172dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                break;
173dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            case Align::ALIGN_RET_FEW_INLIERS:
174dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                frames_size++;
175dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                ret = MOSAIC_RET_FEW_INLIERS;
176dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                break;
177dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            case Align::ALIGN_RET_LOW_TEXTURE:
178dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                ret = MOSAIC_RET_LOW_TEXTURE;
179dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                break;
180dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            case Align::ALIGN_RET_ERROR:
181dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                ret = MOSAIC_RET_ERROR;
182dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                break;
183dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            default:
184dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                break;
185e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        }
186e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
187dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
188dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    return ret;
189e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
190e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
191e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
192e1178a73fd5756771d25d0b8375452450f509e99mbansalint Mosaic::createMosaic(float &progress, bool &cancelComputation)
193e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
19450f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen    if (frames_size <= 0)
19550f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen    {
19650f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen        // Haven't accepted any frame in aligner. No need to do blending.
19750f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen        progress = TIME_PERCENT_ALIGN + TIME_PERCENT_BLEND
19850f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen                + TIME_PERCENT_FINAL;
19950f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen        return MOSAIC_RET_OK;
20050f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen    }
20150f36b9eaa0e177cf220737e322576437f051da3Wei-Ta Chen
202e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (blendingType == Blend::BLEND_TYPE_PAN)
203e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
204e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
205e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        balanceRotations();
206e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
207e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
208e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
209274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen    int ret = Blend::BLEND_RET_ERROR;
210e1178a73fd5756771d25d0b8375452450f509e99mbansal
211e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Blend the mosaic (alignment has already been done)
212e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if (blender != NULL)
213e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
214b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal        ret = blender->runBlend((MosaicFrame **) frames, (MosaicFrame **) rframes,
215b28b9c0fa991bc97e8aa11da83d27f71fdfef6dambansal                frames_size, imageMosaicYVU,
216e1178a73fd5756771d25d0b8375452450f509e99mbansal                mosaicWidth, mosaicHeight, progress, cancelComputation);
217e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
218e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
219e1178a73fd5756771d25d0b8375452450f509e99mbansal    switch(ret)
220e1178a73fd5756771d25d0b8375452450f509e99mbansal    {
221e1178a73fd5756771d25d0b8375452450f509e99mbansal        case Blend::BLEND_RET_ERROR:
222e1178a73fd5756771d25d0b8375452450f509e99mbansal        case Blend::BLEND_RET_ERROR_MEMORY:
223e1178a73fd5756771d25d0b8375452450f509e99mbansal            ret = MOSAIC_RET_ERROR;
224e1178a73fd5756771d25d0b8375452450f509e99mbansal            break;
225e1178a73fd5756771d25d0b8375452450f509e99mbansal        case Blend::BLEND_RET_CANCELLED:
226e1178a73fd5756771d25d0b8375452450f509e99mbansal            ret = MOSAIC_RET_CANCELLED;
227e1178a73fd5756771d25d0b8375452450f509e99mbansal            break;
228e1178a73fd5756771d25d0b8375452450f509e99mbansal        case Blend::BLEND_RET_OK:
229e1178a73fd5756771d25d0b8375452450f509e99mbansal            ret = MOSAIC_RET_OK;
230e1178a73fd5756771d25d0b8375452450f509e99mbansal    }
231e1178a73fd5756771d25d0b8375452450f509e99mbansal    return ret;
232e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
233e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
234e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenImageType Mosaic::getMosaic(int &width, int &height)
235e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
236e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    width = mosaicWidth;
237e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    height = mosaicHeight;
238e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
239e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return imageMosaicYVU;
240e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
241e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
242e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
243e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
244e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Mosaic::balanceRotations()
245e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
246e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Normalize to the mean angle of rotation (Smiley face)
247e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double sineAngle = 0.0;
248e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
249e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int i = 0; i < frames_size; i++) sineAngle += frames[i]->trs[0][1];
250e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    sineAngle /= frames_size;
251e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Calculate the cosineAngle (1 - sineAngle*sineAngle) = cosineAngle*cosineAngle
252e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double cosineAngle = sqrt(1.0 - sineAngle*sineAngle);
253e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double m[3][3] = {
254e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        { cosineAngle, -sineAngle, 0 },
255e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        { sineAngle, cosineAngle, 0},
256e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        { 0, 0, 1}};
257e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    double tmp[3][3];
258e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
259e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    for (int i = 0; i < frames_size; i++) {
260e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        memcpy(tmp, frames[i]->trs, sizeof(tmp));
261e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        mult33d(frames[i]->trs, m, tmp);
262e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
263e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
264e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return MOSAIC_RET_OK;
265e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
266