Index.cpp 8.64 KB
Newer Older
daFischer's avatar
daFischer committed
1 2
/* 
 * File:   Index.cpp
3
 * Author: Johannes Fischer
daFischer's avatar
daFischer committed
4 5 6 7 8 9 10 11
 * 
 * Created on July 23, 2014, 10:10 PM
 */

#include "Index.h"
#include "Inflater.h"

Index::Index(Inflater* in, int numBytes) {
12
    waypoint = NULL;
daFischer's avatar
daFischer committed
13 14 15
    this->numBytes=numBytes;
    in->readShort(&entryNumber);
    this->numBytes -= 2;
16
    
daFischer's avatar
daFischer committed
17 18
}

19
Index::Index(Message** messages, int numMessages) {
20
    waypoint = NULL;
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
    if (VERBOSE)
        printf("\ncompute index table:\n");

    // TODO: set as option
    // possible slide should at least cover 20% of maximum size
    int minSlideArea = ProtocolPreferences::framebufferWidth * ProtocolPreferences::framebufferHeight / 5;

    // TODO: set as option
    // there should be at least 5 or 10 sec between two slides
    int minSlideDiffMsecs = 10000;
    int minSequenceLength = 5;

    // count sequence with gaps less than minSlideDiffMsecs
    int animationCount = 0;

    int timestamp = -minSlideDiffMsecs * 2;
    int previous_timestamp = -1;
    int area = 0;

    // build index based on covered area
    for (int i = 0; i < numMessages; i++) {
        Message* message = messages[i];

        // sum up area(s)
45
        if (message->type == FRAMEBUFFER) {
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
            area += message->getArea();
            //printf("%d,",area);
        } else if (area == 0)
            // only FramebufferUpdates are useful - skip others
            // Note: do not skip if same timestamp as previous framebufferupdate
            continue;

        // cumulate areas of same timestamp
        if (i + 1 < numMessages && message->timestamp == messages[i + 1]->timestamp)
            continue;

        // check size
        if (area > minSlideArea) {
            // reset cumulated area
            area = 0;
            // no animation or first index
            if ((message->timestamp - timestamp > minSlideDiffMsecs) || index.size() == 0) {
                if (animationCount > 0 && animationCount < minSequenceLength && previous_timestamp >= 0) {
                    // no animation, take last message of sequence
                    // (animations take first message of sequence as index)
                    index.push_back(new IndexEntry(NULL, previous_timestamp, NULL, NULL));
                    if (index.size() > 0)
                        index.back()->timestamp = previous_timestamp;
                    else
                        // first index
                        index.push_back(new IndexEntry(NULL, previous_timestamp, NULL, NULL));
                    if (VERBOSE)
                        printf(" RESET");
                }

                animationCount = 0;

                if (VERBOSE)
                    cout << "\nIndex " << (index.size() < 9 ? " " : "") << (index.size() + 1) << ": " << message->timestamp;
                index.push_back(new IndexEntry(NULL, message->timestamp, NULL, NULL));
            } else {
                // distinguish animations from multiple slide changes
                animationCount++;
                previous_timestamp = message->timestamp;

                if (VERBOSE)
                    cout << "\t" << message->timestamp << "(" << animationCount << ")";
            }
            timestamp = message->timestamp;
        }
    }

    // fix last index if needed
    if (animationCount > 0 && animationCount < minSequenceLength && previous_timestamp >= 0 && index.size() > 0) {
        // no animation, take last message of sequence
        // (animations take first message of sequence as index)
        index.back()->timestamp = previous_timestamp;
        if (VERBOSE)
            printf(" RESET");
    }

    if ((index.size() > 0)
            && (index.back()->timestamp >= messages[numMessages - 1]->timestamp)) {
        index.pop_back();
        if (VERBOSE)
            printf(" - Removing last index, because it uses timestamp of last message->");
    }

    // add index at beginning if needed
    if (index.size() == 0 || index.front()->timestamp > 2000) {
        index.push_front(new IndexEntry(NULL, 0, NULL, NULL));
        if (VERBOSE)
            printf("\nIndex added index at beginning.");
    }

    if (VERBOSE)
        printf("\n\nGenerated index with %d entries.\n\n", index.size());
    it = index.begin();
119
    currentMessage=0;
120 121
}

daFischer's avatar
daFischer committed
122 123 124
SDL_Surface* Index::readThumbnail(Inflater* in, int* numBytes) {
    int imageSize;
    in->readInt(&imageSize);
125 126
    *numBytes -= 4;
    if (imageSize == 0)
daFischer's avatar
daFischer committed
127 128
        // thumbnail not available
        return NULL;
129 130 131 132 133 134 135
    else {
        //printf("Index numBytes = %d, imageSize = %d\n",*numBytes, imageSize);
        char* imageArray;// = (char*) malloc(imageSize);
        imageArray = in->readCharArray(imageSize, false);
        *numBytes -= imageSize;
        SDL_RWops* source=SDL_RWFromMem((void*) imageArray, imageSize);
        SDL_Surface* bufferedImage = IMG_Load_RW(source, 0);
daFischer's avatar
daFischer committed
136 137 138 139 140
        delete(imageArray);
        return bufferedImage;
    }
}

141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
bool Index::readIndexEntry(Inflater* in) {
    int timestamp;
    unsigned char titleLength;
    char* title;
    int searchableLength;
    SizedArray* searchableArray;
    SDL_Surface* image;
    
    if(entryNumber>0) {
        entryNumber--;
        in->readInt(&timestamp);
        in->readByte((char*) &titleLength);
        title = in->readCharArray(titleLength, true);
        title[titleLength] = 0;
        in->readInt(&searchableLength);
        searchableArray = new SizedArray(searchableLength);
        in->readSizedArray(searchableArray);

        numBytes -= 9 + titleLength + searchableLength;
        image = readThumbnail(in, &numBytes);
        index.push_back(new IndexEntry(title, timestamp, searchableArray, image));
        return true;
    }
    
    if (numBytes > 0) {
        printf("Index skipping %d bytes\n", numBytes);
        in->skipBytes(numBytes);
    }
    it = index.begin();
170
    currentMessage=0;
171 172 173 174 175 176 177 178 179 180
    //TODO: what if too many bytes have been read?
    
    return false;
}

/* Video calls this when a not yet filled IndexEntry needs to be filled immediately
 */
void Index::loadUntil(IndexEntry* entry, SDL_Surface* screen, Message** messages, int numMessages, ProtocolPreferences* prefs) {
    if(VERBOSE)
        printf("Loading IndexEntries from %d s until %d s\n",(*it)->timestamp/1000,entry->timestamp/1000);
181 182
    for(; it!=index.end() && (*it)->timestamp<=entry->timestamp;)//'it' is incremented in fillSurface
        fillSurface(screen,messages,numMessages,1000000,prefs);
183 184 185
}


186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
bool Index::fillSurface(SDL_Surface* screen, Message** messages, int numMessages, int areaLeft, ProtocolPreferences* prefs) {
    if (it == index.end() || currentMessage >= numMessages)
    {
        progress=-1;
        return false;
    }
    while(areaLeft > 0 && currentMessage < numMessages && it != index.end())
    {
        if (messages[currentMessage]->timestamp > (*it)->timestamp)
        {
            progress=(*it)->timestamp;
            (*it)->setWaypoint(waypoint);
            it++;
            if (it == index.end())
            {
                progress=-1;
                return false;
            }
            waypoint=NULL;
        }
        if(waypoint==NULL)
            waypoint = SDL_CreateRGBSurface(SDL_ANYFORMAT, screen->w, screen->h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
        
        if (messages[currentMessage]->type == FRAMEBUFFER)
        {
            messages[currentMessage]->paint(waypoint, prefs);
            areaLeft-=messages[currentMessage]->getArea();
        }
        currentMessage++;
    }
    return true;
    /*if (it == index.end())
daFischer's avatar
daFischer committed
218
        return false;
219 220 221

    SDL_Surface* waypoint = SDL_CreateRGBSurface(SDL_ANYFORMAT, screen->w, screen->h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
    if (it == index.begin()) {
222
        printf("First Message for IndexEntry\n");
223 224 225 226 227 228 229 230 231 232
        currentMessage = 0;
    } else {
        it--;
        (*it)->paintWaypoint(waypoint);
        it++;
    }

    while (currentMessage < numMessages) {
        if (messages[currentMessage]->timestamp > (*it)->timestamp)
            break;
233
        if (messages[currentMessage]->type == FRAMEBUFFER)
234 235 236 237 238 239
            messages[currentMessage]->paint(waypoint, prefs);
        currentMessage++;
    }
    (*it)->setWaypoint(waypoint);

    it++;
240 241 242 243
    if (it == index.end())
        progress=-1;
    else
        progress=(*it)->timestamp;
244
    return true;*/
245 246
}

daFischer's avatar
daFischer committed
247
IndexEntry* Index::lastBefore(int timestamp) {
248
    for (std::list<IndexEntry*>::reverse_iterator it = index.rbegin(); it != index.rend(); it++)
249
        if ((*it)->timestamp <= timestamp)
250 251 252
        {
            return (IndexEntry*) * it;
        }
daFischer's avatar
daFischer committed
253 254 255 256
    return index.front();
}

Index::~Index() {
257 258 259 260
    while (index.size() > 0) {
        delete(index.front());
        index.pop_front();
    }
daFischer's avatar
daFischer committed
261 262
}