status_t MovieEncoder::Encode() { int32 framesLeft = fFileList->CountItems(); int32 framesWritten = 0; if (framesLeft <= 0) { DisposeData(); BMessage message(kEncodingFinished); message.AddInt32("status", (int32)B_ERROR); fMessenger.SendMessage(&message); return B_ERROR; } // Create movie char movieName[B_FILE_NAME_LENGTH]; MakeUniqueName(fOutputFile.Path(), movieName, B_FILE_NAME_LENGTH); entry_ref movieRef; get_ref_for_path(movieName, &movieRef); media_file_format fileFormat; if (!GetMediaFileFormat(fFamily, fileFormat)) { BMessage message(kEncodingFinished); message.AddInt32("status", (int32)B_ERROR); fMessenger.SendMessage(&message); return B_ERROR; } BBitmap* bitmap = BTranslationUtils::GetBitmapFile(fFileList->ItemAt(0)); BRect sourceFrame = bitmap->Bounds(); delete bitmap; if (!fDestFrame.IsValid()) fDestFrame = sourceFrame.OffsetToCopy(B_ORIGIN); BitmapMovie* movie = new BitmapMovie(fDestFrame.IntegerWidth() + 1, fDestFrame.IntegerHeight() + 1, fColorSpace); status_t error = movie->CreateFile(movieRef, fileFormat, fFormat, fCodecInfo); if (error < B_OK) { delete movie; DisposeData(); BMessage message(kEncodingFinished); message.AddInt32("status", (int32)error); fMessenger.SendMessage(&message); return error; } // Bitmap and view used to convert the source bitmap // to the correct size and depth BBitmap* destBitmap = new BBitmap(fDestFrame, fColorSpace, true); BView* destDrawer = new BView(fDestFrame, "drawing view", B_FOLLOW_NONE, 0); if (destBitmap->Lock()) { destBitmap->AddChild(destDrawer); destBitmap->Unlock(); } const uint32 keyFrameFrequency = 10; BMessage progressMessage(B_UPDATE_STATUS_BAR); progressMessage.AddFloat("delta", 1.0); bool keyFrame = true; for (int32 i = 0; i < fFileList->CountItems(); i++) { if (framesWritten % keyFrameFrequency == 0) keyFrame = true; const char* fileName = fFileList->ItemAt(i); BBitmap* frame = BTranslationUtils::GetBitmapFile(fileName); if (frame == NULL) continue; // Draw scaled if (error == B_OK) { destBitmap->Lock(); destDrawer->DrawBitmap(frame, frame->Bounds(), destDrawer->Bounds()); destDrawer->Sync(); destBitmap->Unlock(); } delete frame; if (error == B_OK) error = movie->WriteFrame(destBitmap, keyFrame); if (error == B_OK) { framesWritten++; keyFrame = false; } else { printf("%s\n", strerror(error)); break; } if (fMessenger.IsValid()) fMessenger.SendMessage(new BMessage(progressMessage)); } //printf("%ld frames written\n", framesWritten); delete movie; delete destBitmap; //delete cursor; DisposeData(); BMessage message(kEncodingFinished); message.AddInt32("status", (int32)B_OK); fMessenger.SendMessage(&message); return B_OK; }
status_t MovieEncoder::Encode() { int32 framesLeft = fFileList->CountItems(); int32 framesWritten = 0; if (framesLeft <= 0) { DisposeData(); BMessage message(kEncodingFinished); message.AddInt32("status", (int32)B_ERROR); fMessenger.SendMessage(&message); return B_ERROR; } // Create movie char movieName[B_FILE_NAME_LENGTH]; MakeUniqueName(fOutputFile.Path(), movieName, B_FILE_NAME_LENGTH); entry_ref movieRef; get_ref_for_path(movieName, &movieRef); BBitmap* bitmap = BTranslationUtils::GetBitmapFile(fFileList->ItemAt(0)); BRect sourceFrame = bitmap->Bounds(); delete bitmap; if (!fDestFrame.IsValid()) fDestFrame = sourceFrame.OffsetToCopy(B_ORIGIN); BitmapMovie* movie = new BitmapMovie(fDestFrame.IntegerWidth() + 1, fDestFrame.IntegerHeight() + 1, fColorSpace); status_t status = movie->CreateFile(movieRef, fFileFormat, fFormat, fCodecInfo); if (status < B_OK) { delete movie; DisposeData(); BMessage message(kEncodingFinished); message.AddInt32("status", (int32)status); fMessenger.SendMessage(&message); return status; } // Bitmap and view used to convert the source bitmap // to the correct size and depth BBitmap* destBitmap = new BBitmap(fDestFrame, fColorSpace, true); BView* destDrawer = new BView(fDestFrame, "drawing view", B_FOLLOW_NONE, 0); if (destBitmap->Lock()) { destBitmap->AddChild(destDrawer); destBitmap->Unlock(); } const uint32 keyFrameFrequency = 10; // TODO: Make this tunable BMessage progressMessage(B_UPDATE_STATUS_BAR); progressMessage.AddFloat("delta", 1.0); status = B_OK; for (int32 i = 0; i < fFileList->CountItems(); i++) { bool keyFrame = (framesWritten % keyFrameFrequency == 0); const char* fileName = fFileList->ItemAt(i); BBitmap* frame = BTranslationUtils::GetBitmapFile(fileName); if (frame == NULL) { // TODO: What to do here ? Exit with an error ? continue; } // Draw scaled if (status == B_OK) { destBitmap->Lock(); destDrawer->DrawBitmap(frame, frame->Bounds(), destDrawer->Bounds()); destDrawer->Sync(); destBitmap->Unlock(); } delete frame; if (status == B_OK) status = movie->WriteFrame(destBitmap, keyFrame); if (status != B_OK) break; framesWritten++; if (fMessenger.IsValid()) fMessenger.SendMessage(new BMessage(progressMessage)); } delete movie; delete destBitmap; DisposeData(); if (fMessenger.IsValid()) { BMessage message(kEncodingFinished); message.AddInt32("status", (int32)status); message.AddInt32("frames", (int32)framesWritten); fMessenger.SendMessage(&message); } return status; }