status_t OutputView::GetCodecsForFamily(const media_format_family &family, const int32 &width, const int32 &height, BMenu *codecs, media_format &initialFormat) { SetInitialFormat(width, height, Settings().ClipDepth(), 10, initialFormat); // find the full media_file_format corresponding to // the given format family (e.g. AVI) media_file_format fileFormat; if (!GetMediaFileFormat(family, fileFormat)) return B_ERROR; BString currentCodec; BMenuItem *marked = codecs->FindMarked(); if (marked != NULL) currentCodec = marked->Label(); // suspend updates while we're rebuilding this menu in order to // reduce window flicker and other annoyances Window()->BeginViewTransaction(); codecs->RemoveItems(0, codecs->CountItems(), true); int32 cookie = 0; media_codec_info codec; media_format dummyFormat; while (get_next_encoder(&cookie, &fileFormat, &initialFormat, &dummyFormat, &codec) == B_OK) { BMenuItem *item = CreateCodecMenuItem(codec); if (item != NULL) codecs->AddItem(item); if (codec.pretty_name == currentCodec) item->SetMarked(true); } if (codecs->FindMarked() == NULL) { BMenuItem *item = codecs->ItemAt(0); if (item != NULL) item->SetMarked(true); } Window()->EndViewTransaction(); marked = codecs->FindMarked(); BMessage *message = marked->Message(); media_codec_info *info; ssize_t size; if (message->FindData(kCodecData, B_SIMPLE_DATA, (const void **)&info, &size) == B_OK) fController->SetMediaCodecInfo(*info); 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); 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; }