Пример #1
0
int
main(int argc, char *argv[])
{
	if (argc != 2) {
		fprintf(stderr, "Usage:\n  %s <filename>\n", argv[0]);
		return 1;
	}
	
	entry_ref ref;
	if (get_ref_for_path(argv[1], &ref)!=B_OK)
		return 2;
	BMediaFile *playFile = new BMediaFile(&ref);
	if (playFile->InitCheck()<B_OK) {
		delete playFile;
		return 2;
	}
	
	for (int ix=0; ix<playFile->CountTracks(); ix++) {
		BMediaTrack * track = playFile->TrackAt(ix);
		playFormat.type = B_MEDIA_RAW_AUDIO;
		if ((track->DecodedFormat(&playFormat) == B_OK) 
			&& (playFormat.type == B_MEDIA_RAW_AUDIO)) {
			playTrack = track;
			break;
		}
		if (track)
			playFile->ReleaseTrack(track);
	}
	// Good relations with the Wookiees, I have. 
	signal(SIGINT, keyb_int);

	new BApplication("application/x-vnd.Antares-playfile");
	finished = create_sem(0, "finish wait");
	
	printf("playing file...\n");
	
	// Execute Plan 66!
	sp = new BSoundPlayer(&playFormat.u.raw_audio, "playfile", play_buffer);
	sp->SetVolume(1.0f);

	// Join me, Padmé and together we can rule this galaxy. 
	sp->SetHasData(true);
	sp->Start();

	acquire_sem(finished);

	if (interrupt) {
		// Once more, the Sith will rule the galaxy. 
		printf("interrupted\n");
		sp->Stop();
		kill_thread(reader);
	}

	printf("playback finished\n");

	delete sp;
	delete playFile;
}
Пример #2
0
AudioTrack*
TrackIO::ImportAudio(BMediaFile* mediaFile, const char* name)
{
	TrackIndex* index = new TrackIndex();

	media_format format;

	MediaFormatBuilder::BuildAudioBlockRawFormat(&format);

	// TODO check original file format to ask 
	// if the user want it to be resampled or not.
	// NOTE atm we are considering only the first track, may and probably will
	// change in future, or at least the user should be able to select which track
	// to import (eventually all and as separated track).
	BMediaTrack* track = mediaFile->TrackAt(0);
	if (track->DecodedFormat(&format) != B_OK) {
		// Critical error show a popup
		return NULL;
	}

	uint32 channels = format.u.raw_audio.channel_count;
	for (uint32 i = 0; i < channels; i++) {
		MediaBlockMap* channel = new MediaBlockMap();
		index->AddChannel(channel);
	}

	WindowsManager::ProgressUpdate(10.0f, "Loading audio data");

	int64 frames = 0;

	int64 bufferFrames = (format.u.raw_audio.buffer_size
		/ (format.u.raw_audio.format 
		& media_raw_audio_format::B_AUDIO_SIZE_MASK));

	float buffer[bufferFrames];

	memset(&buffer, 0, format.u.raw_audio.buffer_size);
	while (track->ReadFrames(buffer, &frames) == B_OK) {
		_BuildBlocks((float*)buffer, frames*channels, index,
			channels);
		memset(&buffer, 0, format.u.raw_audio.buffer_size);
	}

	WindowsManager::ProgressUpdate(50.0f, "Flushing data and preview");

	mediaFile->ReleaseTrack(track);

	// This is done to optimize writes, the data is cached in a buffer
	// and then written to the BPositionIO.
	for (uint32 j = 0; j < index->CountChannels(); j++)
		index->ChannelAt(j)->Writer()->Flush();

	return new AudioTrack(name, index);
}
Пример #3
0
MediaFilePlayer::MediaFilePlayer(const char* media_type,
	const char* media_name, entry_ref* ref)
	:
	fName(media_name),
	fInitCheck(B_ERROR),
	fRef(*ref),
	fSoundPlayer(NULL),
	fPlayTrack(NULL)
{
	fPlayFile = new BMediaFile(&fRef);
	fInitCheck = fPlayFile->InitCheck();
	if (fInitCheck != B_OK)
		return;

	memset(&fPlayFormat, 0, sizeof(fPlayFormat));

	for (int i=0; i < fPlayFile->CountTracks(); i++) {
		BMediaTrack* track = fPlayFile->TrackAt(i);
		if (track == NULL)
			continue;
		fPlayFormat.type = B_MEDIA_RAW_AUDIO;
		fPlayFormat.u.raw_audio.buffer_size = 256;
		if ((track->DecodedFormat(&fPlayFormat) == B_OK)
			&& (fPlayFormat.type == B_MEDIA_RAW_AUDIO)) {
			fPlayTrack = track;
			break;
		}
		fPlayFile->ReleaseTrack(track);
	}

	if (fPlayTrack == NULL) {
		fInitCheck = B_BAD_VALUE;
		return;
	}

	fSoundPlayer = new BSoundPlayer(&fPlayFormat.u.raw_audio,
		media_name, PlayFunction, NULL, this);

	fInitCheck = fSoundPlayer->InitCheck();
	if (fInitCheck != B_OK)
		return;

	fSoundPlayer->SetVolume(1.0f);
	fSoundPlayer->SetHasData(true);
	fSoundPlayer->Start();
}
Пример #4
0
void 
MediaFileInfoView::_GetFileInfo(BString* audioFormat, BString* videoFormat,
	BString* audioDetails, BString* videoDetails, BString* duration)
{
	fDuration = 0;
	if (fMediaFile == NULL)
		return;
	
	BMediaTrack* track;
	media_format format;
	memset(&format, 0, sizeof(format));
	media_codec_info codecInfo;
	bool audioDone(false), videoDone(false);
	bigtime_t audioDuration = 0;
	bigtime_t videoDuration = 0;
	int32 tracks = fMediaFile->CountTracks();
	int64 videoFrames = 0;
	int64 audioFrames = 0;
	for (int32 i = 0; i < tracks && (!audioDone || !videoDone); i++) {
		track = fMediaFile->TrackAt(i);
		if (track != NULL) {
			track->EncodedFormat(&format);
			if (format.IsVideo()) {
				memset(&format, 0, sizeof(format));
				format.type = B_MEDIA_RAW_VIDEO;
				track->DecodedFormat(&format);
				media_raw_video_format *rvf = &(format.u.raw_video);

				track->GetCodecInfo(&codecInfo);
				*videoFormat << codecInfo.pretty_name;
				videoDuration = track->Duration();
				videoFrames = track->CountFrames();

				*videoDetails << (int32)format.Width() << "x" << (int32)format.Height()
							 << " " << (int32)(rvf->field_rate / rvf->interlace)
							 << " fps / "  << videoFrames << " frames";

				videoDone = true;

			} else if (format.IsAudio()) {
				memset(&format, 0, sizeof(format));
				format.type = B_MEDIA_RAW_AUDIO;
				track->DecodedFormat(&format);
				media_raw_audio_format *raf = &(format.u.raw_audio);
				char bytesPerSample = (char)(raf->format & 0xf);
				if (bytesPerSample == 1) {
					*audioDetails << "8 bit ";
				} else if (bytesPerSample == 2) {
					*audioDetails << "16 bit ";
				} else {
					*audioDetails << bytesPerSample << "byte ";
				}

				track->GetCodecInfo(&codecInfo);
				*audioFormat << codecInfo.pretty_name;
				audioDuration = track->Duration();
				audioFrames = track->CountFrames();

				*audioDetails << (float)(raf->frame_rate / 1000.0f) << " kHz";
				if (raf->channel_count == 1) {
					*audioDetails << " mono / ";
				} else if (raf->channel_count == 2) {
					*audioDetails << " stereo / ";
				} else {
					*audioDetails << (int32)raf->channel_count << " channel / " ;
				}
				*audioDetails << audioFrames << " frames";
				audioDone = true;
			}
			fMediaFile->ReleaseTrack(track);
		}	
	}

	fDuration = MAX(audioDuration, videoDuration);
	*duration << (int32)(fDuration / 1000000)
			  << " seconds";
}
Пример #5
0
status_t
MainView::LoadWave(const entry_ref& ref)
{
	bigtime_t startLoadWave = system_time();

	fDestCursor = 0;
	fSourceCursor = 0;
	fAverage = 0.0f;
	fAverageCursor = 0;
	fDownsamplingWidth = 0;
	fDownsampleCount = 0;

	// instantiate a BMediaFile object, and make sure there was no error.
	/*BEntry entry("./song.wav");
	entry_ref ref;
	entry.GetRef(&ref);*/
	BMediaFile* mediaFile = new BMediaFile(&ref);
	status_t err = mediaFile->InitCheck();
	if (err != B_OK) {
		printf("cannot contruct BMediaFile object -- %s\n", strerror(err));
		return err;
	}

	for (int32 i = 0; i < mediaFile->CountTracks(); i++) {
		BMediaTrack* track = mediaFile->TrackAt(i);
		if (track == NULL) {
			printf("cannot contruct BMediaTrack object\n");
			return B_ERROR;
		}

		media_format format;
		format.type = B_MEDIA_RAW_AUDIO;
		format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
		err = track->DecodedFormat(&format);
		if (err != B_OK) {
			printf("BMediaTrack::DecodedFormat error -- %s\n", strerror(err));
			return err;
		}

		if (format.type == B_MEDIA_RAW_AUDIO) {

			// get the actual sourceWindow.left obtained by seeking
			bigtime_t start = system_time();
			int64 actualSeekFrame = fSourceWindow.left;
			err = track->SeekToFrame(&actualSeekFrame);
			if (err != B_OK) {
				printf("BMediaTrack::SeekToFrame(%lli) error -- %s\n", fSourceWindow.left, strerror(err));
				return err;
			}
			printf("BMediaTrack::SeekToFrame(%lli) seekedto=%lli in %llims\n", fSourceWindow.left, actualSeekFrame, (system_time() - start) / 1000);
			fSourceWindow.left = actualSeekFrame;

			frame_range destWindow(0, (uint64) fWaveFrame.Width());
			int64 totalSourceFrameCount = track->CountFrames();
			fDownsamplingWidth = fSourceWindow.Width() / destWindow.Width();

			printf("Source window left=%lli right=%lli width=%lli (total=%lli)\n", fSourceWindow.left, fSourceWindow.right, fSourceWindow.Width(), totalSourceFrameCount);
			printf("Dest window left=%lli right=%lli width=%lli\n", destWindow.left, destWindow.right, destWindow.Width());
			printf("Downsampling width=%lli\n", fDownsamplingWidth);

			delete [] fWave;
			fWave = NULL;
			fWave = new(std::nothrow) float[fSourceWindow.Width() / fDownsamplingWidth]; // ATT: on en prend plus que la largeur de dest car downsampling width entier
			if (fWave == NULL)
				return B_NO_MEMORY;

			char* buffer = new(std::nothrow) char[format.u.raw_audio.buffer_size];
			if (buffer == NULL)
				return B_NO_MEMORY;

			int64 readFrameCount = 0;
			media_header mediaHeader;
			fSourceCursor = fSourceWindow.left;
			for(int64 j = 0; j < fSourceWindow.Width(); j += readFrameCount) {

				err = track->ReadFrames(buffer, &readFrameCount, &mediaHeader);
				if (err) {
					printf("BMediaTrack::ReadFrames error -- %s\n", strerror(err));
					delete [] buffer;
					break;
					// TODO fatal error?
				}

				if (fSourceCursor + readFrameCount >= fSourceWindow.right) {
					readFrameCount = fSourceWindow.right - fSourceCursor;
					printf("yes readFrameCount = %lli\n", readFrameCount);
				}

				_ProcessAudio(buffer, &format, readFrameCount);
			}
			printf("Source cursor %li (read %li)\n", fSourceCursor, fSourceCursor - fSourceWindow.left);
			printf("Dest cursor %li\n", fDestCursor);

			delete [] buffer;
		}

		mediaFile->ReleaseTrack(track);
	}
	delete mediaFile;


	printf("LoadWave in %lims\n", (system_time() - startLoadWave) / 1000 );
	fCurrentEntryRef = ref;
	return B_OK;
}
Пример #6
0
void LeftList::MessageReceived(BMessage* msg)
{
	struct AudioInfo fAudioInfo;
	BMediaFile* testfile;
	bool fIsAudio = false;
	BMediaTrack* track;
	media_codec_info codecInfo;
	media_format format;
	memset(&format, 0, sizeof(format));

	entry_ref ref;
	int32 counter = 0;

	switch (msg->what) {

		case B_SIMPLE_DATA:
			while (msg->FindRef("refs", counter++, &ref) == B_OK) {
				if ((testfile = new BMediaFile(&ref)) != NULL) {
					testfile->InitCheck();
					track = testfile->TrackAt(0);
					if (track != NULL) {
						track->EncodedFormat(&format);
						if (format.IsAudio()) {
							memset(&format, 0, sizeof(format));
							format.type = B_MEDIA_RAW_AUDIO;
							track->DecodedFormat(&format);
							fAudioInfo.total_time = track->Duration();
							media_raw_audio_format* raf = &(format.u.raw_audio);
							fAudioInfo.bps = (int32)(raf->format & 0xf);
							fAudioInfo.frame_rate = (int32)raf->frame_rate;
							fAudioInfo.channels = (int32)raf->channel_count;
							track->GetCodecInfo(&codecInfo);
							strcpy(fAudioInfo.pretty_name, codecInfo.pretty_name);
							strcpy(fAudioInfo.short_name, codecInfo.short_name);
							fIsAudio = true;
						}
					}
				} else
					WriteLog("MediaFile NULL (file doesnt exists!?)");

				delete testfile;
				if (fIsAudio) {
					if (!strcmp(fAudioInfo.pretty_name, "Raw Audio") && (fAudioInfo.channels == 2) && (fAudioInfo.frame_rate == 44100) && (fAudioInfo.bps == 2))
						AddItem(new LeftListItem(&ref, ref.name, fAudioBitmap, &fAudioInfo));
					else {
						BAlert* MyAlert = new BAlert("BurnItNow", "You can only burn 16 bits stereo 44.1 kHz Raw Audio files.\n (More audio files will be supported in the future)", "Ok", NULL, NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT);
						MyAlert->Go();
					}
				} else {
					BPath temp_path;
					BEntry(&ref).GetPath(&temp_path);
					jpWindow* win = dynamic_cast<jpWindow*>(Window());
					if (win != NULL)
						win->SetISOFile((char*)temp_path.Path());
				}
			}
			break;
		default:
			BListView::MessageReceived(msg);
			break;
	}
}
Пример #7
0
int media_play(const char* uri)
{
	BUrl url;
	entry_ref ref;
	BMediaFile* playFile;

	if (get_ref_for_path(uri, &ref) != B_OK) {
		url.SetUrlString(uri);
		if (url.IsValid()) {
			playFile = new BMediaFile(url);
		} else
			return 2;
	} else
		playFile = new BMediaFile(&ref);

	if (playFile->InitCheck() != B_OK) {
		delete playFile;
		return 2;
	}
	
	for (int i = 0; i < playFile->CountTracks(); i++) {
		BMediaTrack* track = playFile->TrackAt(i);
		playFormat.type = B_MEDIA_RAW_AUDIO;
		if ((track->DecodedFormat(&playFormat) == B_OK) 
				&& (playFormat.type == B_MEDIA_RAW_AUDIO)) {
			playTrack = track;
			break;
		}
		if (track)
			playFile->ReleaseTrack(track);
	}

	// Good relations with the Wookiees, I have. 
	signal(SIGINT, keyb_int);

	finished = create_sem(0, "finish wait");
	
	printf("Playing file...\n");
	
	// Execute Plan 66!
	player = new BSoundPlayer(&playFormat.u.raw_audio, "playfile", play_buffer);
	player->SetVolume(1.0f);

	// Join me, Padmé and together we can rule this galaxy. 
	player->SetHasData(true);
	player->Start();

	acquire_sem(finished);

	if (interrupt == true) {
		// Once more, the Sith will rule the galaxy. 
		printf("Interrupted\n");
		player->Stop();
		kill_thread(reader);
	}

	printf("Playback finished.\n");

	delete player;
	delete playFile;

	return 0;
}
int
main(int argc, char *argv[])
{
	// 256 frames * 4 buffer parts * 2 channels * 2 bytes per sample
	// will give us internal buffer of 4096 bytes
	size_t framesPerBufferPart = 256;
	size_t bufferPartCount = 4;

	if (argc != 2 && argc != 4) {
		printf("Usage: %s <sound file name> [<frames per part> <parts>]\n",
			argv[0]);
		return 0;
	}

	if (argc == 4) {
		size_t size = strtoul(argv[2], NULL, 10);
		if (size > 0)
			framesPerBufferPart = size;

		size = strtoul(argv[3], NULL,  10);
		if (size == 1) {
			printf("at least 2 buffer parts are needed\n");
			return 1;
		}
		if (size > 0)
			bufferPartCount = size;
	}

	printf("frames per buffer part: %ld\n", framesPerBufferPart);
	printf("buffer part count: %ld\n", bufferPartCount);

	BEntry entry(argv[1]);
	if (entry.InitCheck() != B_OK || !entry.Exists()) {
		printf("cannot open input file\n");
		return 1;
	}

	entry_ref entryRef;
	entry.GetRef(&entryRef);

	BMediaFile mediaFile(&entryRef);
	if (mediaFile.InitCheck() != B_OK) {
		printf("file not supported\n");
		return 1;
	}

	if (mediaFile.CountTracks() == 0) {
		printf("no tracks found in file\n");
		return 1;
	}

	BMediaTrack *mediaTrack = mediaFile.TrackAt(0);
	if (mediaTrack == NULL) {
		printf("problem getting track from file\n");
		return 1;
	}

	// propose format, let it decide frame rate, channels number and buf size
	media_format format;
	memset(&format, 0, sizeof(format));
	format.type = B_MEDIA_RAW_AUDIO;
	format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT;
	format.u.raw_audio.byte_order = B_MEDIA_LITTLE_ENDIAN;

	if (mediaTrack->DecodedFormat(&format) != B_OK) {
		printf("cannot set decoder output format\n");
		return 1;
	}

	printf("negotiated format:\n");
	printf("frame rate: %g Hz\n", format.u.raw_audio.frame_rate);
	printf("channel count: %ld\n", format.u.raw_audio.channel_count);
	printf("buffer size: %ld bytes\n", format.u.raw_audio.buffer_size);

	gs_audio_format gsFormat;
	memset(&gsFormat, 0, sizeof(gsFormat));
	gsFormat.frame_rate = format.u.raw_audio.frame_rate;
	gsFormat.channel_count = format.u.raw_audio.channel_count;
	gsFormat.format = format.u.raw_audio.format;
	gsFormat.byte_order = format.u.raw_audio.byte_order;

	BPushGameSound pushGameSound(framesPerBufferPart, &gsFormat,
		bufferPartCount);
	if (pushGameSound.InitCheck() != B_OK) {
		printf("trouble initializing push game sound: %s\n",
			strerror(pushGameSound.InitCheck()));
		return 1;
	}

	uint8 *buffer;
	size_t bufferSize;
	if (pushGameSound.LockForCyclic((void **)&buffer, &bufferSize)
			!= BPushGameSound::lock_ok) {
		printf("cannot lock buffer\n");
		return 1;
	}
	memset(buffer, 0, bufferSize);

	if (pushGameSound.StartPlaying() != B_OK) {
		printf("cannot start playback\n");
		return 1;
	}

	printf("playing, press [esc] to exit...\n");

	uint8 decoded[format.u.raw_audio.buffer_size * 2];
	size_t bufferPartSize = framesPerBufferPart
		* format.u.raw_audio.channel_count
		* (format.u.raw_audio.format
			& media_raw_audio_format::B_AUDIO_SIZE_MASK);
	size_t decodedSize = 0;
	size_t partPos = 0;
	size_t pos = 0; /*pushGameSound.CurrentPosition();*/
	key_info keyInfo;

	while (true) {
		// fill buffer part with data from decoded buffer
		while (partPos < bufferPartSize && decodedSize) {
			size_t size = min_c(bufferPartSize - partPos, decodedSize);

			memcpy(buffer + pos + partPos, decoded, size);
			partPos += size;

			decodedSize -= size;
			memmove(decoded, decoded + size, decodedSize);
		}

		// if there are too little data to fill next buffer part
		// read next decoded frames
		if (partPos < bufferPartSize) {
			int64 frameCount;
			if (mediaTrack->ReadFrames(decoded + decodedSize, &frameCount)
					!= B_OK)
				break;
			if (frameCount == 0)
				break;

			decodedSize += frameCount * format.u.raw_audio.channel_count
				* (format.u.raw_audio.format
					& media_raw_audio_format::B_AUDIO_SIZE_MASK);

			printf("\rtime: %.2f",
				(double)mediaTrack->CurrentTime() / 1000000LL);
			fflush(stdout);

			continue;
		}

		// this buffer part is done
		partPos = 0;
		pos += bufferPartSize;
		if (bufferSize <= pos)
			pos = 0;

		// playback sync - wait for the buffer part we're about to fill to be
		// played
		while (pushGameSound.CurrentPosition() >= pos + bufferPartSize
			|| pushGameSound.CurrentPosition() < pos)
			snooze(1000 * framesPerBufferPart / gsFormat.frame_rate);

		// check escape key state
		if (get_key_info(&keyInfo) != B_OK) {
			printf("\nkeyboard state read error\n");
			break;
		}
		if ((keyInfo.key_states[0] & 0x40) != 0)
			break;
	}

	pushGameSound.StopPlaying();

	mediaFile.ReleaseTrack(mediaTrack);
	mediaFile.CloseFile();

	printf("\nfinished.\n");

	return 0;
}
Пример #9
0
status_t
MediaFileInfo::LoadInfo(BMediaFile* file)
{
	_Reset();
	if (!file)
		return B_BAD_VALUE;
	
	BMediaTrack* track;
	media_format format;
	memset(&format, 0, sizeof(format));
	media_codec_info codecInfo;
	bool audioDone(false), videoDone(false);
	bigtime_t audioDuration = 0;
	bigtime_t videoDuration = 0;
	int32 tracks = file->CountTracks();
	int64 videoFrames = 0;
	int64 audioFrames = 0;
	status_t ret = B_OK;

	for (int32 i = 0; i < tracks && (!audioDone || !videoDone); i++) {
		track = file->TrackAt(i);
		if (track == NULL)
			return B_ERROR;

		ret = track->InitCheck();
		if (ret != B_OK)
			return ret;

		ret = track->EncodedFormat(&format);
		if (ret != B_OK)
			return ret;

		if (format.IsVideo()) {
			memset(&format, 0, sizeof(format));
			format.type = B_MEDIA_RAW_VIDEO;

			ret = track->DecodedFormat(&format);
			if (ret != B_OK)
				return ret;

			media_raw_video_format *rvf = &(format.u.raw_video);

			ret = track->GetCodecInfo(&codecInfo);
			if (ret != B_OK)
				return ret;

			video.format << codecInfo.pretty_name;
			videoDuration = track->Duration();
			videoFrames = track->CountFrames();

			BString details;
			snprintf(details.LockBuffer(256), 256,
					B_TRANSLATE_COMMENT("%u x %u, %.2ffps / %Ld frames",
					"Width x Height, fps / frames"),
					format.Width(), format.Height(),
					rvf->field_rate / rvf->interlace, videoFrames);
			details.UnlockBuffer();
			video.details << details;
			videoDone = true;

		} else if (format.IsAudio()) {
			memset(&format, 0, sizeof(format));
			format.type = B_MEDIA_RAW_AUDIO;
			ret = track->DecodedFormat(&format);
			if (ret != B_OK)
				return ret;
			media_raw_audio_format *raf = &(format.u.raw_audio);
			char bytesPerSample = (char)(raf->format & 0xf);

			BString details;
			if (bytesPerSample == 1 || bytesPerSample == 2) {
				snprintf(details.LockBuffer(16), 16,
						B_TRANSLATE("%d bit "), bytesPerSample * 8);
			} else {
				snprintf(details.LockBuffer(16), 16,
						B_TRANSLATE("%d byte "), bytesPerSample);
			}
			details.UnlockBuffer();
			audio.details << details;

			ret = track->GetCodecInfo(&codecInfo);
			if (ret != B_OK)
				return ret;

			audio.format << codecInfo.pretty_name;
			audioDuration = track->Duration();
			audioFrames = track->CountFrames();
			BString channels;
			if (raf->channel_count == 1) {
				snprintf(channels.LockBuffer(64), 64,
				B_TRANSLATE("%.1f kHz mono / %lld frames"), 
				raf->frame_rate / 1000.f, audioFrames);
			} else if (raf->channel_count == 2) {
				snprintf(channels.LockBuffer(64), 64,
				B_TRANSLATE("%.1f kHz stereo / %lld frames"), 
				raf->frame_rate / 1000.f, audioFrames);
			} else {
				snprintf(channels.LockBuffer(64), 64,
				B_TRANSLATE("%.1f kHz %ld channel / %lld frames"), 
				raf->frame_rate / 1000.f, raf->channel_count, audioFrames);
			}
			channels.UnlockBuffer();
			audio.details << channels;

			audioDone = true;
		}
		ret = file->ReleaseTrack(track);
		if (ret != B_OK)
			return ret;
	}

	useconds = MAX(audioDuration, videoDuration);
	duration << (int32)(useconds / 1000000)
			  << B_TRANSLATE(" seconds");

	return B_OK;
}
Пример #10
0
status_t
MediaView::SetMediaSource(BPositionIO *data)
{
	BAutolock autolock(Window());

	fMediaFile = new BMediaFile(data);
	
	file = data;
	
	bool	foundTrack = false;
	int32	numTracks = fMediaFile->CountTracks();

	for (int32 i = 0; i < numTracks; i++) {
		BMediaTrack *track = fMediaFile->TrackAt(i);
		
		if (track == NULL) {
			Reset();
			return (B_ERROR);
		}
		else {
			bool			trackUsed = false;
			media_format	mf;

			if (track->EncodedFormat(&mf) == B_NO_ERROR) {			
				switch (mf.type) {
					case B_MEDIA_ENCODED_VIDEO:
printf("#################field rate %f\n", mf.u.encoded_video.output.field_rate);
						trackUsed = SetVideoTrack(data, track, &mf) == B_NO_ERROR;
						break;
	
					case B_MEDIA_RAW_AUDIO:
						trackUsed = SetAudioTrack(data, track, &mf) == B_NO_ERROR;
						break;
						
					case B_MEDIA_ENCODED_AUDIO:
						if (track->DecodedFormat(&mf) == B_NO_ERROR)			
							trackUsed = SetAudioTrack(data, track, &mf) == B_NO_ERROR;
						break;

					default:
						break;
				}
			}
	
			if (trackUsed)
				foundTrack = true;
			else {
				fMediaFile->ReleaseTrack(track);
			}
		}
	}

	if (foundTrack) {
		status_t err = B_ERROR;
	
		fPlayerThread = spawn_thread(MediaView::MediaPlayer, 
									 "MediaView::MediaPlayer",
									 95,
									 this);
	
		if (fPlayerThread < B_NO_ERROR) {
			err = fPlayerThread;
			fPlayerThread = B_ERROR;
			Reset();
	
			return (err);
		}
	
		fPlaySem = create_sem(0, "MediaView::fPlaySem");
		if (fPlaySem < B_NO_ERROR) {
			err = fPlaySem;
			fPlaySem = B_ERROR;
			Reset();

			return (err);
		}

		err = resume_thread(fPlayerThread);
	
		if (err != B_NO_ERROR) {
			kill_thread(fPlayerThread);
			fPlayerThread = B_ERROR;
			Reset();

			return (err);
		}

		if (fVideoTrack != NULL)
			fMediaBar->SetTotalTime(fVideoTrack->Duration());
		else
			fMediaBar->SetTotalTime(fAudioTrack->Duration());			
	}
	return (B_NO_ERROR);
}
Пример #11
0
void MyApplication::RefsReceived(BMessage *message)
{
//	be_app->Lock();

	uint32			ref_num;
	entry_ref		ref;
	BMediaTrack 	*audTrack(NULL);
	media_format	format;
	memset(&format, 0, sizeof(format));
//	media_raw_audio_format *raf(NULL);
//	short			audioFrameSize(1);
//	char			*audioData(NULL);
	int32			frame_size, channels = 1;
	
	Pool.sample_type = NONE;		// for frame moving / resize
	bool temp_pause = play_cookie.pause;;

	ref_num=0;
	if (message->FindRef("refs",ref_num, &ref) == B_OK){

		BMediaFile		inFile(&ref);
		if (inFile.InitCheck() == B_OK){

			char s[B_FILE_NAME_LENGTH +20];
			sprintf(s, "BeAE - %s", ref.name);
			mainWindow->SetTitle(s);

			Pool.sample_view_dirty = true;	// update the sample-view
			Pool.update_index = true;
			Pool.RedrawWindow();
			play_cookie.pause = true;

			// gather the necessary format information
			int32 tracks = inFile.CountTracks();
			for (int32 i = 0; i < tracks; i++) {
				BMediaTrack *inTrack = inFile.TrackAt(i);
				inTrack->EncodedFormat(&format);

				if (format.IsAudio()) {
					audTrack = inTrack;
					inTrack->DecodedFormat(&format);

//					Pool.m_format = format;
					memcpy(&Pool.m_format, &format, sizeof(Pool.m_format));

					Pool.sample_bits = (format.u.raw_audio.format & 0xf)*8;
					Pool.selection = NONE;
					Pool.frequency = format.u.raw_audio.frame_rate;

//					printf("format : %x\n", format.u.raw_audio.format);

					Pool.size = audTrack->CountFrames()-1;
					channels = format.u.raw_audio.channel_count;

					Pool.StartProgress(Language.get("LOADING_FILE"), Pool.size);
					
					frame_size = (format.u.raw_audio.format & 0xf)*channels;

#ifndef __VM_SYSTEM	//RAM
					if (Pool.sample_memory)						// create buffer for sample memory, add an extra frame to be able to do
						free(Pool.sample_memory);				//  32bit to 16 bit conversions
					
					Pool.sample_memory = (float*)malloc(Pool.size * channels *4 +1024);
#endif					
				}else{
					inFile.ReleaseAllTracks();
				}
			}

			int64 frameCount, framesRead;
			status_t err;
			media_header mh;
			int32 lastPercent, currPercent;
			float completePercent;
			BString status;
			char *buffer = (char*)malloc(format.u.raw_audio.buffer_size);		// temp memory
#ifndef __VM_SYSTEM	//RAM
			float *mem = Pool.sample_memory;									// dest memory
			// read audio from source and write to destination, if necessary
			if (mem) {
#else
			VM.Reset();

			float *convert_buffer = (float*)malloc(format.u.raw_audio.buffer_size*4);		// make sure there can be floats in it
			// read audio from source and write to destination, if necessary
			if (convert_buffer) {
				float *mem = NULL;
#endif			
				frameCount = audTrack->CountFrames();
				int64 count =0;
				lastPercent = -1;
				for (int64 i = 0; i < frameCount; i += framesRead) {
				
					#ifdef __VM_SYSTEM	//RAM
					mem = convert_buffer;
					#endif
					
					// clear buffer first
					memset( buffer, 0, format.u.raw_audio.buffer_size);
					if ((err = audTrack->ReadFrames(buffer, &framesRead, &mh)) != B_OK) {
						printf("Error reading audio frames: %s\n", strerror(err));
						break;
					}

					count += framesRead;			// now correct for crashes if bigger than file
					if (count > frameCount)
						framesRead -= (count - frameCount);
		
					switch(format.u.raw_audio.format){
					case 0x24:	// 0 == mid, -1.0 == bottom, 1.0 == top (the preferred format for non-game audio)
					{	float *tmp = (float*)buffer;
						float x;
						for (int32 count = 0; count<framesRead*channels; count++){
							x = *tmp++;
							if (x<-1.0)		x = -1.0;
							else if (x>1.0)	x = 1.0;
							*mem++ = x;
						}
					}	break;
					case 0x4:	// 0 == mid, 0x80000001 == bottom, 0x7fffffff == top (all >16-bit formats, left-adjusted)
					{	int32 *tmp = (int32*)buffer;
						float x;
						for (int32 count = 0; count<framesRead*channels; count++){
							x = *tmp++/0x80000000;
							if (x<-1.0)		x = -1.0;
							else if (x>1.0)	x = 1.0;
							*mem++ = x;
						}
					}	break;
					case 0x2:	// 0 == mid, -32767 == bottom, +32767 == top
					{	int16 *tmp = (int16*)buffer;
						float x;
						for (int32 count = 0; count<framesRead*channels; count++){
							x = *tmp++/32767.0;
							if (x<-1.0)		x = -1.0;
							else if (x>1.0)	x = 1.0;
							*mem++ = x;
						}
					}	break;
					case 0x11:	// 128 == mid, 1 == bottom, 255 == top (discouraged but supported format)
					{	uint8 *tmp = (uint8*)buffer;
						float x;
						for (int32 count = 0; count<framesRead*channels; count++){
							x = *tmp++/127.0 -1.0;
							if (x<-1.0)		x = -1.0;
							else if (x>1.0)	x = 1.0;
							*mem++ = x;
						}
					}	break;
					case 0x1:		// 0 == mid, -127 == bottom, +127 == top (not officially supported format)
					{	int8 *tmp = (int8*)buffer;
						float x;
						for (int32 count = 0; count<framesRead*channels; count++){
							x = *tmp++/127.0;		// xor 128 to invert sign bit
							if (x<-1.0)		x = -1.0;
							else if (x>1.0)	x = 1.0;
							*mem++ = x;
						}
					}	break;
					}
					
					#ifdef __VM_SYSTEM	//RAM
					VM.WriteBlock( convert_buffer, framesRead*channels );
					#endif

					Pool.ProgressUpdate( framesRead );

					completePercent = ((float)i) / ((float)frameCount) * 100;
					currPercent = (int16)floor(completePercent);
					if (currPercent > lastPercent) {
						lastPercent = currPercent;
					}
				}
				inFile.ReleaseAllTracks();
				#ifdef __VM_SYSTEM	//RAM
				free(convert_buffer);
				#endif
			}else{
				Pool.play_mode = NONE;
				Pool.pointer = 0;
				Pool.play_pointer = 0;
				Pool.l_pointer = 0;
				Pool.r_pointer = 0;
				Pool.r_sel_pointer = 0;
				Pool.size = 0;
				Pool.selection = NONE;
				Pool.sample_type = NONE;
				Pool.sample_bits = 16;
				Pool.frequency = 41400.0;

		         (new BAlert(NULL,Language.get("MEM_ERROR"),Language.get("OK")))->Go();

			}
			
			if (channels == 1)
				Pool.sample_type = MONO;
			else
				Pool.sample_type = STEREO;

			Pool.r_pointer = Pool.size;
			Pool.pointer = 0;
			Pool.r_sel_pointer = Pool.pointer;
			Pool.l_pointer = 0;

#ifndef __VM_SYSTEM	//RAM
			play_cookie.mem = Pool.sample_memory;
			play_cookie.start_mem = Pool.sample_memory;
			play_cookie.end_mem = Pool.sample_memory + Pool.size*Pool.sample_type;
			play_cookie.frequency = Pool.frequency;
			play_cookie.add = 0;
#else			
			play_cookie.mem = 0;
			play_cookie.start_mem = 0;
//			play_cookie.end_mem = Pool.size*Pool.sample_type;
			play_cookie.frequency = Pool.frequency;
			play_cookie.add = 0;
#endif
			Pool.changed = false;
			Pool.HideProgress();

			// create the PeakFile
			Pool.ResetIndexView();
			Hist.Reset();				// reset undo class

			if (IsLaunching() && Prefs.play_when_loaded)
				Pool.mainWindow->PostMessage(TRANSPORT_PLAYS);
			
		}else{
			(new BAlert(NULL,Language.get("LOADING_NO_AUDIO"),Language.get("OK")))->Go();
		}
	}
	
	Pool.sample_view_dirty = true;	// update the sample-view
	Pool.update_draw_cache = true;	// update the draw cache
	Pool.update_index = true;		// update the draw cache
	Pool.update_peak = true;
	Pool.RedrawWindow();
	Pool.InitBufferPlayer( Pool.frequency );

	play_cookie.pause = temp_pause;
	Pool.UpdateMenu();
	mainWindow->UpdateRecent();
//	be_app->Unlock();
}

//------------------------------------------------------------------ Save

void MyApplication::Save(BMessage *message){
	// Grab the stuff we know is there .. or should be :P

	entry_ref dir_ref, file_ref;
	const char *name;
	BFile newFile;
	BDirectory dir;
	float t;
	
	if ((message->FindRef("directory", &dir_ref) == B_OK)
		&& (message->FindString("name", &name) == B_OK))
	{
		dir.SetTo(&dir_ref);
		if (dir.InitCheck() != B_OK)
			return;
			
		dir.CreateFile(name, &newFile);
		
		BEntry entry(&dir, name);
		if (entry.InitCheck() != B_OK) {
			(new BAlert(NULL, Language.get("CANT_OVERWRITE_FILE"), Language.get("OK")))->Go();
			return;
		}
		entry.GetRef(&file_ref);

		media_codec_info *audioCodec;
		media_file_format *fileFormat;
		media_raw_audio_format *raf(NULL), *raf_in(NULL);
		media_format format;
		memset(&format, 0, sizeof(format));
		char *buffer(NULL);
		int32 frame_size(1);

		fSavePanel->GetSelectedFormatInfo(&fileFormat, &audioCodec);

		if (audioCodec != NULL){

//			format = Pool.m_format;
			memcpy(&format, &Pool.m_format, sizeof(format));
			raf_in = &(format.u.raw_audio);
			format.type = B_MEDIA_RAW_AUDIO;

			if (raf_in->format == 1)	raf_in->format = 0x11;
			
			// create media file
			BMediaFile file(&file_ref, fileFormat, B_MEDIA_FILE_REPLACE_MODE);
			if (file.InitCheck() != B_OK){
				(new BAlert(NULL, Language.get("CANT_OVERWRITE_FILE"), Language.get("OK")))->Go();
				return;
			}
			
			BMediaTrack *outTrack = file.CreateTrack(&format, audioCodec);

			if (outTrack){
				file.CommitHeader();

				if (save_start == 0){			// save as
					char s[B_FILE_NAME_LENGTH +20];
					sprintf(s, "BeAE - %s", file_ref.name);
					mainWindow->SetTitle(s);
				}

				raf = &(format.u.raw_audio);
				buffer = (char*)malloc(raf->buffer_size);
				int32 channels = raf->channel_count;
				frame_size = (raf->format & 0xf) * raf->channel_count;
				
				int32 buffer_step = raf->buffer_size / frame_size;
#ifndef __VM_SYSTEM	//RAM
				float *mem = Pool.sample_memory + save_start*Pool.sample_type;	// src memory
#else
				float *convert_buffer = (float*)malloc(buffer_step*channels*4);		// make sure there can be floats in it
				// read audio from source and write to destination, if necessary
				if (convert_buffer) {
					VM.ReadBlockAt(save_start, convert_buffer, buffer_step*channels );
					float *mem = convert_buffer;
#endif			

				Pool.StartProgress(Language.get("SAVING_FILE"), save_end-save_start);
				for (int64 i=save_start; i<save_end; i+=buffer_step){

				// fill up the buffer

					int32 block = MIN( (save_end-i) , buffer_step);
					switch(format.u.raw_audio.format){
					case 0x24:	// 0 == mid, -1.0 == bottom, 1.0 == top (the preferred format for non-game audio)
					{	float *tmp = (float*)buffer;
						for (int32 count = 0; count<block*channels; count++){
							*tmp++ = *mem++;
						}
					}	break;
					case 0x4:	// 0 == mid, 0x80000001 == bottom, 0x7fffffff == top (all >16-bit formats, left-adjusted)
					{	int32 *tmp = (int32*)buffer;
						for (int32 count = 0; count<block*channels; count++){
							t = *mem++;
							*tmp++ = ROUND(t*0x7fffffff);
						}
					}	break;
					case 0x2:	// 0 == mid, -32767 == bottom, +32767 == top
					{	int16 *tmp = (int16*)buffer;
						for (int32 count = 0; count<block*channels; count++){
							t = *mem++;
							*tmp++ = ROUND(t*32767.0);
						}
					}	break;
					case 0x11:	// 128 == mid, 1 == bottom, 255 == top (discouraged but supported format)
					{	uint8 *tmp = (uint8*)buffer;
						for (int32 count = 0; count<block*channels; count++){
							t = *mem++;
							*tmp = ROUND(t*127.0);
							tmp++;
							*tmp = *tmp ^ 0x80;
						}
					}	break;
					case 0x1:		// 0 == mid, -127 == bottom, +127 == top (not officially supported format)
					{	int8 *tmp = (int8*)buffer;
						for (int32 count = 0; count<block*channels; count++){
							t = *mem++;
							*tmp++ = ROUND(t*127.0);		// xor 128 to invert sign bit
						}
					}	break;
					}

					Pool.ProgressUpdate( block );
					outTrack->WriteFrames(buffer, block);
					#ifdef __VM_SYSTEM	//RAM
					VM.ReadBlock(convert_buffer, block*channels );
					mem = convert_buffer;
					#endif
				}

				#ifdef __VM_SYSTEM	//RAM
				free(convert_buffer);
				}
				#endif
				
				Pool.changed = false;

				outTrack->Flush();

				BMimeType result;
				BEntry ent(&dir,name);
				entry_ref fref;
				ent.GetRef(&fref);
				BMimeType::GuessMimeType(&fref,&result);
				BNodeInfo ninfo(&newFile); 
				ninfo.SetType(result.Type()); 

			}else{
				(new BAlert(NULL, Language.get("CODEC_FORMAT_ERROR"), Language.get("OK")))->Go();
			}

			file.CloseFile();
			
			free(buffer);
			Pool.HideProgress();
		}
	}else{
		(new BAlert(NULL, Language.get("SAVE_ERROR"), Language.get("OK")))->Go();
	}

	if (Pool.save_mode == 2)
		PostMessage(B_QUIT_REQUESTED);
	if (Pool.save_mode == 1)
		mainWindow->PostMessage(OPEN);

	Pool.save_mode = 0;
}
status_t
MediaConverterApp::_ConvertFile(BMediaFile* inFile, BMediaFile* outFile,
	media_codec_info* audioCodec, media_codec_info* videoCodec,
	int32 audioQuality, int32 videoQuality,
	bigtime_t startDuration, bigtime_t endDuration)
{
	BMediaTrack* inVidTrack = NULL;
	BMediaTrack* inAudTrack = NULL;
	BMediaTrack* outVidTrack = NULL;
	BMediaTrack* outAudTrack = NULL;

	media_format inFormat;
	media_format outAudFormat;
	media_format outVidFormat;

	media_raw_audio_format* raf = NULL;
	media_raw_video_format* rvf = NULL;

	int32 width = -1;
	int32 height = -1;

	uint8* videoBuffer = NULL;
	uint8* audioBuffer = NULL;

	// gather the necessary format information and construct output tracks
	int64 videoFrameCount = 0;
	int64 audioFrameCount = 0;

	status_t ret = B_OK;

	int32 tracks = inFile->CountTracks();
	for (int32 i = 0; i < tracks && (!outAudTrack || !outVidTrack); i++) {
		BMediaTrack* inTrack = inFile->TrackAt(i);
		memset(&inFormat, 0, sizeof(media_format));
		inTrack->EncodedFormat(&inFormat);
		if (inFormat.IsAudio() && (audioCodec != NULL)) {
			inAudTrack = inTrack;
			memset(&outAudFormat, 0, sizeof(media_format));
			outAudFormat.type = B_MEDIA_RAW_AUDIO;
			raf = &(outAudFormat.u.raw_audio);
			inTrack->DecodedFormat(&outAudFormat);

			audioBuffer = new uint8[raf->buffer_size];
//			audioFrameSize = (raf->format & media_raw_audio_format::B_AUDIO_SIZE_MASK)
//			audioFrameSize = (raf->format & 0xf) * raf->channel_count;
			outAudTrack = outFile->CreateTrack(&outAudFormat, audioCodec);

			if (outAudTrack != NULL) {
				if (outAudTrack->SetQuality(audioQuality / 100.0f) != B_OK
					&& fWin->Lock()) {
					fWin->SetAudioQualityLabel(
						B_TRANSLATE("Audio quality not supported"));
					fWin->Unlock();
				}
			}

		} else if (inFormat.IsVideo() && (videoCodec != NULL)) {
			inVidTrack = inTrack;
			width = (int32)inFormat.Width();
			height = (int32)inFormat.Height();

			// construct desired decoded video format
			memset(&outVidFormat, 0, sizeof(outVidFormat));
			outVidFormat.type = B_MEDIA_RAW_VIDEO;
			rvf = &(outVidFormat.u.raw_video);
			rvf->last_active = (uint32)(height - 1);
			rvf->orientation = B_VIDEO_TOP_LEFT_RIGHT;
			rvf->display.format = B_RGB32;
			rvf->display.bytes_per_row = 4 * width;
			rvf->display.line_width = width;
			rvf->display.line_count = height;

			inVidTrack->DecodedFormat(&outVidFormat);

			if (rvf->display.format == B_RGBA32) {
				printf("fixing color space (B_RGBA32 -> B_RGB32)");
				rvf->display.format = B_RGB32;
			}
			// Transfer the display aspect ratio.
			if (inFormat.type == B_MEDIA_ENCODED_VIDEO) {
				rvf->pixel_width_aspect
					= inFormat.u.encoded_video.output.pixel_width_aspect;
				rvf->pixel_height_aspect
					= inFormat.u.encoded_video.output.pixel_height_aspect;
			} else {
				rvf->pixel_width_aspect
					= inFormat.u.raw_video.pixel_width_aspect;
				rvf->pixel_height_aspect
					= inFormat.u.raw_video.pixel_height_aspect;
			}

			videoBuffer = new (std::nothrow) uint8[height
				* rvf->display.bytes_per_row];
			outVidTrack = outFile->CreateTrack(&outVidFormat, videoCodec);

			if (outVidTrack != NULL) {
				// DLM Added to use 3ivx Parameter View
				const char* videoQualitySupport = NULL;
				BView* encoderView = outVidTrack->GetParameterView();
				if (encoderView) {
					MediaEncoderWindow* encoderWin
						= new MediaEncoderWindow(BRect(50, 50, 520, 555),
							encoderView);
					encoderWin->Go();
						// blocks until the window is quit

					// The quality setting is ignored by the 3ivx encoder if the
					// view was displayed, but this method is the trigger to read
					// all the parameter settings
					outVidTrack->SetQuality(videoQuality / 100.0f);

					// We can now delete the encoderView created for us by the encoder
					delete encoderView;
					encoderView = NULL;

					videoQualitySupport = 
						B_TRANSLATE("Video using parameters form settings");
				} else {
					if (outVidTrack->SetQuality(videoQuality / 100.0f) >= B_OK)
						videoQualitySupport = 
							B_TRANSLATE("Video quality not supported");
				}
				if (videoQualitySupport && fWin->Lock()) {
					fWin->SetVideoQualityLabel(videoQualitySupport);
					fWin->Unlock();
				}
			}
		} else {
			//  didn't do anything with the track
			inFile->ReleaseTrack(inTrack);
		}
	}

	if (!outVidTrack && !outAudTrack) {
		printf("MediaConverterApp::_ConvertFile() - no tracks found!\n");
		ret = B_ERROR;
	}

	if (fCancel) {
		// don't have any video or audio tracks here, or cancelled
		printf("MediaConverterApp::_ConvertFile()"
				" - user canceled before transcoding\n");
		ret = B_CANCELED;
	}

	if (ret < B_OK) {
		delete[] audioBuffer;
		delete[] videoBuffer;
		delete outFile;
		return ret;
	}

	outFile->CommitHeader();
	// this is where you would call outFile->AddCopyright(...)

	int64 framesRead;
	media_header mh;
	int32 lastPercent, currPercent;
	float completePercent;
	BString status;

	int64 start;
	int64 end;
	int32 stat = 0;

	// read video from source and write to destination, if necessary
	if (outVidTrack != NULL) {
		lastPercent = -1;
		videoFrameCount = inVidTrack->CountFrames();
		if (endDuration == 0 || endDuration < startDuration) {
			start = 0;
			end = videoFrameCount;
		} else {
			inVidTrack->SeekToTime(&endDuration, stat);
			end = inVidTrack->CurrentFrame();
			inVidTrack->SeekToTime(&startDuration, stat);
			start = inVidTrack->CurrentFrame();
			if (end > videoFrameCount)
				end =  videoFrameCount;
			if (start > end)
				start = 0;
		}

		framesRead = 0;
		for (int64 i = start; (i <= end) && !fCancel; i += framesRead) {
			if ((ret = inVidTrack->ReadFrames(videoBuffer, &framesRead,
					&mh)) != B_OK) {
				fprintf(stderr, "Error reading video frame %" B_PRId64 ": %s\n", i,
						strerror(ret));
				snprintf(status.LockBuffer(128), 128,
						B_TRANSLATE("Error read video frame %" B_PRId64), i);
				status.UnlockBuffer();
				SetStatusMessage(status.String());

				break;
			}

			if ((ret = outVidTrack->WriteFrames(videoBuffer, framesRead,
					mh.u.encoded_video.field_flags)) != B_OK) {
				fprintf(stderr, "Error writing video frame %" B_PRId64 ": %s\n", i,
						strerror(ret));
				snprintf(status.LockBuffer(128), 128,
						B_TRANSLATE("Error writing video frame %" B_PRId64), i);
				status.UnlockBuffer();
				SetStatusMessage(status.String());

				break;
			}
			completePercent = (float)(i - start) / (float)(end - start) * 100;
			currPercent = (int32)completePercent;
			if (currPercent > lastPercent) {
				lastPercent = currPercent;
				snprintf(status.LockBuffer(128), 128,
					B_TRANSLATE("Writing video track: %" B_PRId32 "%% complete"),
					currPercent);
				status.UnlockBuffer();
				SetStatusMessage(status.String());

			}
		}
		outVidTrack->Flush();
		inFile->ReleaseTrack(inVidTrack);
	}

	// read audio from source and write to destination, if necessary
	if (outAudTrack != NULL) {
		lastPercent = -1;

		audioFrameCount =  inAudTrack->CountFrames();

		if (endDuration == 0 || endDuration < startDuration) {
			start = 0;
			end = audioFrameCount;
		} else {
			inAudTrack->SeekToTime(&endDuration, stat);
			end = inAudTrack->CurrentFrame();
			inAudTrack->SeekToTime(&startDuration, stat);
			start = inAudTrack->CurrentFrame();
			if (end > audioFrameCount)
				end = audioFrameCount;
			if (start > end)
				start = 0;
		}

		for (int64 i = start; (i <= end) && !fCancel; i += framesRead) {
			if ((ret = inAudTrack->ReadFrames(audioBuffer, &framesRead,
				&mh)) != B_OK) {
				fprintf(stderr, "Error reading audio frames: %s\n", strerror(ret));
				snprintf(status.LockBuffer(128), 128,
					B_TRANSLATE("Error read audio frame %" B_PRId64), i);
				status.UnlockBuffer();
				SetStatusMessage(status.String());

				break;
			}

			if ((ret = outAudTrack->WriteFrames(audioBuffer,
				framesRead)) != B_OK) {
				fprintf(stderr, "Error writing audio frames: %s\n",	strerror(ret));
				snprintf(status.LockBuffer(128), 128,
					B_TRANSLATE("Error writing audio frame %" B_PRId64), i);
				status.UnlockBuffer();
				SetStatusMessage(status.String());

				break;
			}
			completePercent = (float)(i - start) / (float)(end - start) * 100;
			currPercent = (int32)completePercent;
			if (currPercent > lastPercent) {
				lastPercent = currPercent;
				snprintf(status.LockBuffer(128), 128,
					B_TRANSLATE("Writing audio track: %" B_PRId32 "%% complete"),
					currPercent);
				status.UnlockBuffer();
				SetStatusMessage(status.String());
			}
		}
		outAudTrack->Flush();
		inFile->ReleaseTrack(inAudTrack);

	}

	outFile->CloseFile();
	delete outFile;

	delete[] videoBuffer;
	delete[] audioBuffer;

	return ret;
}