char* BitmapHandler::loadBmpURL(const std::string &name, int &width, int &height, int mode, bool useCache) { char *data=NULL; AmigoRest restClient(amigoCoreAgent.c_str()); restClient.enableCacheWrite(useCache); RestClient::response response = restClient.get(name); if (!response.isBad()) { data = decompressImage((char*)response.body.c_str(), response.body.size(), width, height, mode); } else { if(useCache) { restClient.enableCacheRead(true); response = restClient.get(name); if (!response.isBad()) { data = decompressImage((char*)response.body.c_str(), response.body.size(), width, height, mode); return data; } } AMIGO_LOG_I(TAG, "::loadBmpURL() FILED to load '%s'\n", name.c_str()); } return data; }
char* BitmapHandler::loadBmpFile(const std::string &fname, int &width, int &height, int mode) { char *data=NULL; int size; char *rawData = ImageUtils::loadFile (fname.c_str(), &size); if (rawData!=NULL) { data = decompressImage(rawData, size, width, height, mode); } else { AMIGO_LOG_W(TAG, "::loadBmpFile() FAILED to load '%s'\n", fname.c_str()); } return data; }
void AnimationResource::load(byte *source, int size) { Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size); sourceS->readUint32LE(); sourceS->readUint32LE(); sourceS->readUint16LE(); _flags = sourceS->readUint16LE(); _width = sourceS->readUint16LE(); _height = sourceS->readUint16LE(); sourceS->readUint32LE(); uint16 frameCount = sourceS->readUint16LE(); sourceS->readUint16LE(); sourceS->readUint16LE(); for (uint16 i = 0; i < frameCount; i++) { sourceS->seek(26 + i * 4); uint32 frameOffs = sourceS->readUint32LE(); sourceS->seek(frameOffs); sourceS->readUint32LE(); sourceS->readUint32LE(); uint16 frameWidth = sourceS->readUint16LE(); uint16 frameHeight = sourceS->readUint16LE(); uint16 cmdOffs = sourceS->readUint16LE(); sourceS->readUint16LE(); uint16 pixelOffs = sourceS->readUint16LE(); sourceS->readUint16LE(); uint16 maskOffs = sourceS->readUint16LE(); sourceS->readUint16LE(); uint16 lineSize = sourceS->readUint16LE(); Graphics::Surface *frame = new Graphics::Surface(); frame->create(frameWidth, frameHeight, Graphics::PixelFormat::createFormatCLUT8()); decompressImage(source + frameOffs, *frame, cmdOffs, pixelOffs, maskOffs, lineSize, 0, 0, 0, _flags & 1); _frames.push_back(frame); } delete sourceS; }
void PictureResource::loadRaw(byte *source, int size) { // Loads a "raw" picture as used in RtZ, LGoP2, Manhole:N&E and Rodney's Funscreen Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size); _hasPalette = (sourceS->readByte() != 0); byte cmdFlags = sourceS->readByte(); byte pixelFlags = sourceS->readByte(); byte maskFlags = sourceS->readByte(); uint16 cmdOffs = sourceS->readUint16LE(); uint16 pixelOffs = sourceS->readUint16LE(); uint16 maskOffs = sourceS->readUint16LE(); uint16 lineSize = sourceS->readUint16LE(); /*uint16 u = */sourceS->readUint16LE(); uint16 width = sourceS->readUint16LE(); uint16 height = sourceS->readUint16LE(); if (cmdFlags || pixelFlags || maskFlags) { warning("PictureResource::loadRaw() Graphic has flags set (%d, %d, %d)", cmdFlags, pixelFlags, maskFlags); } _paletteColorCount = (cmdOffs - 18) / 3; // 18 = sizeof header debug(2, "width = %d; height = %d\n", width, height); if (_hasPalette) { _picturePalette = new byte[_paletteColorCount * 3]; sourceS->read(_picturePalette, _paletteColorCount * 3); } _picture = new Graphics::Surface(); _picture->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); decompressImage(source, *_picture, cmdOffs, pixelOffs, maskOffs, lineSize, cmdFlags, pixelFlags, maskFlags); delete sourceS; }
void PictureResource::loadChunked(byte *source, int size) { // Loads a "chunked" picture as used in Manhole EGA Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size); byte cmdFlags = 0, pixelFlags = 0, maskFlags = 0; uint16 cmdOffs = 0, pixelOffs = 0, maskOffs = 0; uint16 lineSize = 0, width = 0, height = 0; sourceS->skip(36); // skip the "Flex" header _hasPalette = false; while (!sourceS->eos()) { uint32 chunkType = sourceS->readUint32BE(); uint32 chunkSize = sourceS->readUint32BE(); if (sourceS->eos()) break; debug(0, "chunkType = %08X; chunkSize = %d", chunkType, chunkSize); if (chunkType == MKTAG('R','e','c','t')) { debug(0, "Rect"); sourceS->skip(4); height = sourceS->readUint16BE(); width = sourceS->readUint16BE(); debug(0, "width = %d; height = %d", width, height); } else if (chunkType == MKTAG('f','M','a','p')) { debug(0, "fMap"); lineSize = sourceS->readUint16BE(); sourceS->skip(11); cmdFlags = sourceS->readByte(); cmdOffs = sourceS->pos(); sourceS->skip(chunkSize - 14); debug(0, "lineSize = %d; cmdFlags = %d; cmdOffs = %04X", lineSize, cmdFlags, cmdOffs); } else if (chunkType == MKTAG('f','L','C','o')) { debug(0, "fLCo"); sourceS->skip(9); pixelFlags = sourceS->readByte(); pixelOffs = sourceS->pos(); sourceS->skip(chunkSize - 10); debug(0, "pixelFlags = %d; pixelOffs = %04X", pixelFlags, pixelOffs); } else if (chunkType == MKTAG('f','P','i','x')) { debug(0, "fPix"); sourceS->skip(9); maskFlags = sourceS->readByte(); maskOffs = sourceS->pos(); sourceS->skip(chunkSize - 10); debug(0, "maskFlags = %d; maskOffs = %04X", maskFlags, maskOffs); } else if (chunkType == MKTAG('f','G','C','o')) { debug(0, "fGCo"); _hasPalette = true; _paletteColorCount = chunkSize / 3; _picturePalette = new byte[_paletteColorCount * 3]; sourceS->read(_picturePalette, _paletteColorCount * 3); } else { error("PictureResource::loadChunked() Invalid chunk %08X at %08X", chunkType, sourceS->pos()); } } if (!cmdOffs || !pixelOffs /*|| !maskOffs*/ || !lineSize || !width || !height) { error("PictureResource::loadChunked() Error parsing the picture data, one or more chunks/parameters are missing"); } _picture = new Graphics::Surface(); _picture->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); decompressImage(source, *_picture, cmdOffs, pixelOffs, maskOffs, lineSize, cmdFlags, pixelFlags, maskFlags); delete sourceS; }
/** \fn DecodePictureUpToIntra \brief Decode pictures from frameno, which must be an intra and on until the decoded frameno is popped by the decoder @param frame, framenumber relative to video ref (i.e. from its beginning) @param ref , video we are dealing with returns true on success fail on error */ bool ADM_Composer::DecodePictureUpToIntra(uint32_t ref,uint32_t frame) { uint8_t ret = 0; EditorCache *cache; ADMImage *result; uint32_t flags,flagsNext=0; ADMCompressedImage img; // PlaceHolder... img.data=compBuffer; img.cleanup(frame); ADM_info(" DecodeUpToInta %u ref:%u\n",frame,ref); _VIDEOS *vid=_segments.getRefVideo(ref); vidHeader *demuxer=vid->_aviheader; cache=vid->_videoCache; ADM_assert(cache); // Make sure frame is an intra, or the next field is intra demuxer->getFlags(frame,&flags); demuxer->getFlags(frame+1,&flagsNext); // in case of field encoding, only the 2nd field might be // flagged as intra uint32_t twoFlags=flags | flagsNext; ADM_assert(twoFlags&AVI_KEY_FRAME); bool found=false; vid->lastSentFrame=frame; uint32_t nbFrames=vid->_nb_video_frames; aprintf("[EditorRender] DecodeUpToIntra flushing cache & codec\n"); cache->flush(); vid->decoder->flush(); // The PTS associated with our frame is the one we are looking for uint64_t wantedPts=demuxer->estimatePts(frame); uint32_t tries=15+7; // Max Ref frames for H264 + MaxRecovery , let's say 7 is ok for recovery bool syncFound=false; while(found==false && tries--) { // Last frame ? if so repeat if(vid->lastSentFrame>=nbFrames-1) vid->lastSentFrame=nbFrames-1; // Fetch frame aprintf("[Editor] Decoding frame %u\n",vid->lastSentFrame); if (!demuxer->getFrame (vid->lastSentFrame,&img)) { ADM_warning(" getFrame failed for frame %"PRIu32"\n",vid->lastSentFrame); //cache->flush(); return false; } // Now uncompress it... result=cache->getFreeImage(); if(frame==0) // out first frame, make sure it starts black to avoid the all green effect { result->blacken(); } if(!result) { ADM_warning(" Cache full for frame %"PRIu32"\n",vid->lastSentFrame); return false; } aprintf("[Decoder] Demuxer Frame %"PRIu32" pts=%"PRIu64" ms, %"PRIu64" us\n",vid->lastSentFrame,img.demuxerPts/1000, img.demuxerPts); if(!decompressImage(result,&img,ref)) { ADM_info(" decode error for frame %"PRIu32", not necessarily a problem\n",vid->lastSentFrame); //cache->dump(); cache->invalidate(result); //cache->dump(); vid->lastSentFrame++; continue; }else { uint64_t pts=result->Pts; aprintf("[Decoder] Decoder Frame %"PRIu32" pts=%"PRIu64" ms, %"PRIu64" us\n",vid->lastSentFrame, result->Pts/1000,result->Pts); if(pts==ADM_COMPRESSED_NO_PTS) // No PTS available ? { if(false==syncFound) { aprintf("[DecodePictureUpToIntra] No time stamp yet, dropping picture\n"); cache->invalidate(result); }else { // increment it using average fps vid->lastDecodedPts+=vid->timeIncrementInUs; result->Pts=vid->lastDecodedPts; } }else { if(false==syncFound) { aprintf("[DecodePictureUpToIntra] Sync found\n"); syncFound=true; } vid->lastDecodedPts=pts; } cache->validate(result); } // Found our image ? if(result->Pts==wantedPts) found=true; else vid->lastSentFrame++; } if(found==false) { ADM_warning(" Could not find decoded frame, wanted PTS :%"PRIu32" PTS=%"PRIu64" ms, %"PRIu64" us\n",frame,wantedPts/1000,wantedPts); cache->dump(); return false; } vid->lastReadPts=wantedPts; currentFrame=frame; return true; }
/** \fn DecodeNextPicture \brief Decode the next picture @param ref , video we are dealing with returns true on success fail on error */ bool ADM_Composer::DecodeNextPicture(uint32_t ref) { uint8_t ret = 0; EditorCache *cache; ADMImage *result; uint32_t flags; ADMCompressedImage img; _VIDEOS *vid=_segments.getRefVideo(ref); vidHeader *demuxer=vid->_aviheader; cache=vid->_videoCache; // PlaceHolder... img.data=compBuffer; img.cleanup(vid->lastSentFrame+1); ADM_assert(cache); vid->lastSentFrame++; uint32_t frame=vid->lastSentFrame; aprintf("[EditorRender] DecodeNext %u ref:%u\n",frame,ref); // Fetch frame aprintf("[Editor] Decoding frame %u\n",frame); if (!demuxer->getFrame (frame,&img)) { ADM_warning("getFrame failed for frame %"PRIu32"\n",vid->lastSentFrame); return false; } // Now uncompress it... result=cache->getFreeImage(); if(!result) { ADM_warning(" Cache full for frame %"PRIu32"\n",vid->lastSentFrame); return false; } aprintf("Demuxed frame %"PRIu32" with pts=%"PRId64" us, %"PRId64" ms\n", frame, img.demuxerPts, img.demuxerPts/1000); if(!decompressImage(result,&img,ref)) { ADM_info("Decoding error for frame %"PRIu32", not necessarily a problem\n",vid->lastSentFrame); stats.nbNoImage++; cache->invalidate(result); return true; // Not an error in itself } aprintf("Got image with PTS=%s\n",ADM_us2plain(result->Pts)); uint64_t pts=result->Pts; uint64_t old=vid->lastDecodedPts; if(pts==ADM_COMPRESSED_NO_PTS) // No PTS available ? { aprintf("[Editor] No PTS, guessing value\n"); aprintf("Image Pts : %s\n",ADM_us2plain(img.demuxerPts)); aprintf("Image Dts : %s\n",ADM_us2plain(img.demuxerDts)); vid->lastDecodedPts+=vid->timeIncrementInUs; if(img.demuxerDts!=ADM_NO_PTS && vid->_aviheader->providePts()==false) { if(img.demuxerDts>vid->lastDecodedPts) { aprintf("Dts > Guessed Pts, cranking pts\n"); vid->lastDecodedPts=img.demuxerDts; } } result->Pts=vid->lastDecodedPts; }else { aprintf("[Editor] got PTS\n"); vid->lastDecodedPts=pts; } aprintf(">>Decoded frame %"PRIu32" with pts=%"PRId64" us, %"PRId64" ms, ptsdelta=%"PRId64" ms \n", frame, vid->lastDecodedPts, vid->lastDecodedPts/1000, (vid->lastDecodedPts-old)/1000); if(old>vid->lastDecodedPts) { stats.nbPtsgoingBack++; ADM_warning(">>>>> PTS going backward by %"PRId64" ms\n",(old-vid->lastDecodedPts)/1000); ADM_warning("Dropping frame!\n"); cache->invalidate(result); return false; }else { cache->validate(result); } if(result->flags & AVI_KEY_FRAME) stats.nbIFrames++; else if(result->flags & AVI_B_FRAME) stats.nbBFrames++; else stats.nbPFrames++; return true; }