/* isAudioDisc * checks if selected files are audio files, and greps the playtime of them * when all files audio files * returns true if audio disc */ bool ProjectTypeSelector::isAudioDisc() { BString *FileType; for(int i = 0; i < TypeList->CountItems(); i++) { FileType = (BString*)TypeList->ItemAt(i); if(FileType->Compare("audio", 5) != 0) return false; } entry_ref ref; BMediaFile *mediaFile; bigtime_t time = 0; for(int i = 0; i < FileList->CountItems(); i++){ get_ref_for_path(((BString*)FileList->ItemAt(i))->String(), &ref); mediaFile = new BMediaFile(&ref); BMediaTrack *track = NULL; for(int j = 0; j < mediaFile->CountTracks(); j++){ track = mediaFile->TrackAt(j); time = track->Duration(); intPlayTime += ((int)time / 1000000); } delete mediaFile; } return true; }
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; }
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); }
/* FUNCTION: Video :: Video ARGUMENTS: ref RETURN: n/a DESCRIPTION: Constructor */ Video :: Video(entry_ref *ref) { fMediaFile = 0; fVideoTrack = 0; fBitmap = 0; fVideoThread = 0; fMediaFile = new BMediaFile(ref, B_MEDIA_FILE_BIG_BUFFERS); fStatus = fMediaFile->InitCheck(); if (fStatus != B_OK) return; int32 num_tracks = fMediaFile->CountTracks(); for (int32 i=0; i < num_tracks; i++) { BMediaTrack *track = fMediaFile->TrackAt(i); if (track == NULL) { fMediaFile->ReleaseAllTracks(); printf("Media file claims to have %ld tracks, cannot find track %ld\n", num_tracks, i); fVideoTrack = 0; return; } media_format mf; fStatus = track->EncodedFormat(&mf); if (fStatus == B_OK) { switch (mf.type) { case B_MEDIA_ENCODED_VIDEO: case B_MEDIA_RAW_VIDEO: if (fVideoTrack == 0) { fVideoTrack = track; InitPlayer(&mf); } else printf("Multiple video tracks not supported\n"); break; default: fStatus = B_ERROR; } } if (fStatus != B_OK) fMediaFile->ReleaseTrack(track); } if (fVideoTrack) fStatus = B_OK; }
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(); }
AudioProducer::~AudioProducer() { TRACE("%p->AudioProducer::~AudioProducer()\n", this); #if DEBUG_TO_FILE BMediaTrack* track; if (BMediaFile* file = init_media_file(fPreferredFormat, &track)) { printf("deleting file...\n"); track->Flush(); file->ReleaseTrack(track); file->CloseFile(); delete file; } #endif // DEBUG_TO_FILE // Stop the BMediaEventLooper thread Quit(); TRACE("AudioProducer::~AudioProducer() done\n"); }
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"; }
// Init status_t VideoClip::Init(const entry_ref* ref) { // check if this file is a MediaFile // instantiate a BMediaFile object, and make sure there was no error. fMediaFile = new BMediaFile(ref); status_t err = fMediaFile->InitCheck(); if (err < B_OK) { fprintf(stderr, "VideoClip::Init() - " "no media file: %s\n", strerror(err)); return err; } // count the tracks and instanciate them, one at a time int32 numTracks = fMediaFile->CountTracks(); for (int32 i = 0; i < numTracks; i++) { if (fTrack) break; BMediaTrack* track = fMediaFile->TrackAt(i); if (!track) { fprintf(stderr, "VideoClip::Init() - " "cannot read media track at %ld\n", i); continue; } // get the encoded format media_format format; err = track->EncodedFormat(&format); if (err < B_OK) { fprintf(stderr, "VideoClip::Init() - " "cannot understand encoded format " "of track %ld: %s\n", i, strerror(err)); continue; } switch(format.type) { case B_MEDIA_RAW_VIDEO: case B_MEDIA_ENCODED_VIDEO: { // video track fTrack = track; break; } case B_MEDIA_RAW_AUDIO: // audio track break; case B_MEDIA_ENCODED_AUDIO: // audio track break; default: break; } if (fTrack != track) { // didn't do anything with the track fMediaFile->ReleaseTrack(track); } } if (!fTrack) return B_UNSUPPORTED; err = fTrack->EncodedFormat(&fFormat); if (err < B_OK) { fprintf(stderr, "VideoClip::Init() - " "fTrack->EncodedFormat(): %s\n", strerror(err)); return err; } // get encoded video frame size uint32 width = fFormat.u.encoded_video.output.display.line_width; uint32 height = fFormat.u.encoded_video.output.display.line_count; printf("VideoClip::Init() - native colorspace: %s\n", string_for_color_space(fFormat.u.encoded_video.output.display.format)); // allocate a buffer large enough to contain the decoded frame. BRect videoBounds(0.0, 0.0, width - 1, height - 1); fBuffer = new BBitmap(videoBounds, 0, B_YCbCr422); err = fBuffer->InitCheck(); if (err < B_OK) { fprintf(stderr, "VideoClip::Init() - " "error allocating buffer: %s\n", strerror(err)); delete fBuffer; fBuffer = NULL; return err; } // specifiy the decoded format. we derive this information from // the encoded format. memset(&fFormat, 0, sizeof(media_format)); fFormat.u.raw_video.last_active = height - 1; // fFormat.u.raw_video.orientation = B_VIDEO_TOP_LEFT_RIGHT; // fFormat.u.raw_video.pixel_width_aspect = 1; // fFormat.u.raw_video.pixel_height_aspect = 1; fFormat.u.raw_video.display.format = fBuffer->ColorSpace(); fFormat.u.raw_video.display.line_width = width; fFormat.u.raw_video.display.line_count = height; fFormat.u.raw_video.display.bytes_per_row = fBuffer->BytesPerRow(); err = fTrack->DecodedFormat(&fFormat); if (err < B_OK) { fprintf(stderr, "VideoClip::Init() - " "fTrack->DecodedFormat(): %s\n", strerror(err)); return err; } fFrameCount = fTrack->CountFrames(); return B_OK; }
BBuffer* AudioProducer::_FillNextBuffer(bigtime_t eventTime) { BBuffer* buffer = fBufferGroup->RequestBuffer( fOutput.format.u.raw_audio.buffer_size, BufferDuration()); if (!buffer) { ERROR("AudioProducer::_FillNextBuffer() - no buffer\n"); return NULL; } size_t sampleSize = fOutput.format.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK; size_t numSamples = fOutput.format.u.raw_audio.buffer_size / sampleSize; // number of sample in the buffer // fill in the buffer header media_header* header = buffer->Header(); header->type = B_MEDIA_RAW_AUDIO; header->time_source = TimeSource()->ID(); buffer->SetSizeUsed(fOutput.format.u.raw_audio.buffer_size); bigtime_t performanceTime = bigtime_t(double(fFramesSent) * 1000000.0 / double(fOutput.format.u.raw_audio.frame_rate)); // fill in data from audio supplier int64 frameCount = numSamples / fOutput.format.u.raw_audio.channel_count; bigtime_t startTime = performanceTime; bigtime_t endTime = bigtime_t(double(fFramesSent + frameCount) * 1000000.0 / fOutput.format.u.raw_audio.frame_rate); if (!fSupplier || fSupplier->InitCheck() != B_OK || fSupplier->GetFrames(buffer->Data(), frameCount, startTime, endTime) != B_OK) { ERROR("AudioProducer::_FillNextBuffer() - supplier error -> silence\n"); memset(buffer->Data(), 0, buffer->SizeUsed()); } // stamp buffer if (RunMode() == B_RECORDING) { header->start_time = eventTime; } else { header->start_time = fStartTime + performanceTime; } #if DEBUG_TO_FILE BMediaTrack* track; if (BMediaFile* file = init_media_file(fOutput.format, &track)) { track->WriteFrames(buffer->Data(), frameCount); } #endif // DEBUG_TO_FILE if (fPeakListener && fOutput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_FLOAT) { // TODO: extend the peak notifier for other sample formats int32 channels = fOutput.format.u.raw_audio.channel_count; float max[channels]; float min[channels]; for (int32 i = 0; i < channels; i++) { max[i] = -1.0; min[i] = 1.0; } float* sample = (float*)buffer->Data(); for (uint32 i = 0; i < frameCount; i++) { for (int32 k = 0; k < channels; k++) { if (*sample < min[k]) min[k] = *sample; if (*sample > max[k]) max[k] = *sample; sample++; } } BMessage message(MSG_PEAK_NOTIFICATION); for (int32 i = 0; i < channels; i++) { float maxAbs = max_c(fabs(min[i]), fabs(max[i])); message.AddFloat("max", maxAbs); } bigtime_t realTime = TimeSource()->RealTimeFor( fStartTime + performanceTime, 0); MessageEvent* event = new (std::nothrow) MessageEvent(realTime, fPeakListener, message); if (event != NULL) EventQueue::Default().AddEvent(event); } return buffer; }
void VideoFileTexture::_Load(const char* fileName) { BEntry entry(fileName); entry_ref ref; entry.GetRef(&ref); fMediaFile = new BMediaFile(&ref); status_t err = fMediaFile->InitCheck(); if (err != B_OK) { printf("cannot contruct BMediaFile object -- %s\n", strerror(err)); return; } int32 trackCount = fMediaFile->CountTracks(); for (int32 i = 0; i < trackCount; i++) { BMediaTrack* track = fMediaFile->TrackAt(i); if (track == NULL) { printf("cannot contruct BMediaTrack object\n"); return; } // get the encoded format media_format format; err = track->EncodedFormat(&format); if (err != B_OK) { printf("BMediaTrack::EncodedFormat error -- %s\n", strerror(err)); return; } if (format.type == B_MEDIA_ENCODED_VIDEO) { fVideoTrack = track; // allocate a bitmap large enough to contain the decoded frame. BRect bounds(0.0, 0.0, format.u.encoded_video.output.display.line_width - 1.0, format.u.encoded_video.output.display.line_count - 1.0); fVideoBitmap = new BBitmap(bounds, B_RGB32); // specifiy the decoded format. we derive this information from // the encoded format. memset(&format, 0, sizeof(media_format)); format.u.raw_video.last_active = (int32) (bounds.Height() - 1.0); format.u.raw_video.orientation = B_VIDEO_TOP_LEFT_RIGHT; format.u.raw_video.pixel_width_aspect = 1; format.u.raw_video.pixel_height_aspect = 3; format.u.raw_video.display.format = fVideoBitmap->ColorSpace(); format.u.raw_video.display.line_width = (int32) bounds.Width(); format.u.raw_video.display.line_count = (int32) bounds.Height(); format.u.raw_video.display.bytes_per_row = fVideoBitmap->BytesPerRow(); err = fVideoTrack->DecodedFormat(&format); if (err != B_OK) { printf("error with BMediaTrack::DecodedFormat() -- %s\n", strerror(err)); return; } // Create Texture glGenTextures(1, &fId); glBindTexture(GL_TEXTURE_2D, fId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, 4, (int) fVideoBitmap->Bounds().Width() + 1, (int) fVideoBitmap->Bounds().Height() + 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, fVideoBitmap->Bits()); } } }
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); }
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; }
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; } }
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; }
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; }
// GetMedia status_t MediaClip::_GetMedia(const entry_ref* ref, BMediaFile*& mediaFile, BMediaTrack** _videoTrack, BMediaTrack** _audioTrack) { if (_videoTrack != NULL) *_videoTrack = NULL; if (_audioTrack != NULL) *_audioTrack = NULL; mediaFile = new BMediaFile(ref); status_t status = mediaFile->InitCheck(); if (status < B_OK) { delete mediaFile; mediaFile = NULL; return status; } // count the tracks and instantiate them, one at a time int32 numTracks = mediaFile->CountTracks(); for (int32 i = 0; i < numTracks; i++) { BMediaTrack* track = mediaFile->TrackAt(i); if (track == NULL) { printf("cannot read media track at %ld\n", i); continue; } // get the encoded format media_format format; status = track->EncodedFormat(&format); if (status < B_OK) { printf("cannot understand encoded format " "of track %ld: %s\n", i, strerror(status)); continue; } bool release = true; switch (format.type) { case B_MEDIA_RAW_VIDEO: case B_MEDIA_ENCODED_VIDEO: { // video track if (_videoTrack != NULL && *_videoTrack == NULL) { *_videoTrack = track; release = false; } break; } case B_MEDIA_RAW_AUDIO: case B_MEDIA_ENCODED_AUDIO: // audio track if (_audioTrack != NULL && *_audioTrack == NULL) { *_audioTrack = track; release = false; } break; default: break; } if (release) { // didn't do anything with the track mediaFile->ReleaseTrack(track); } } return B_OK; }
int32 MediaView::MediaPlayer( void *arg) { MediaView* view = (MediaView *)arg; BWindow* window = view->Window(); BBitmap* bitmap = view->fBitmap; BMediaTrack* videoTrack = view->fVideoTrack; BMediaTrack* audioTrack = view->fAudioTrack; BMediaTrack* counterTrack = (videoTrack != NULL) ? videoTrack : audioTrack; AudioOutput* audioOutput = view->fAudioOutput; void* adBuffer = view->fAudioDumpingBuffer; int64 numFrames = counterTrack->CountFrames(); int64 numFramesToSkip = 0; int64 numSkippedFrames = 0; bool scrubbing = false; bool seekNeeded = false; int64 dummy; media_header mh; bigtime_t vStartTime, aStartTime, seekTime, snoozeTime, startTime; bigtime_t curScrubbing, lastScrubbing, lastTime; curScrubbing = lastScrubbing = system_time(); seekTime = 0LL; // Main processing loop (handle stop->start->stop) while (acquire_sem(view->fPlaySem) == B_OK) { release_sem(view->fPlaySem); // as we are doing stop->start, restart audio if needed. if (audioTrack != NULL) audioOutput->Play(); startTime = system_time()-counterTrack->CurrentTime(); // This will loop until the end of the stream while ((counterTrack->CurrentFrame() < numFrames) || scrubbing) { // We are in scrub mode if (acquire_sem(view->fScrubSem) == B_OK) { curScrubbing = system_time(); // We are entering scrub mode if (!scrubbing) { if (audioTrack != NULL) audioOutput->Stop(); scrubbing = true; } // Do a seek. seekNeeded = true; seekTime = view->fScrubTime; } // We are not scrubbing else if (scrubbing) { if (audioTrack != NULL) audioOutput->Play(); scrubbing = false; } // Handle seeking if (seekNeeded) { if (videoTrack) { // Seek the seekTime as close as possible vStartTime = seekTime; videoTrack->SeekToTime(&vStartTime); // Read frames until we get less than 50ms ahead. lastTime = vStartTime; do { bitmap->LockBits(); status_t err = videoTrack->ReadFrames((char*)bitmap->Bits(), &dummy, &mh); bitmap->UnlockBits(); if (err != B_OK) break; vStartTime = mh.start_time; if ((dummy == 0) || (vStartTime <= lastTime)) break; lastTime = vStartTime; } while (seekTime - vStartTime > 50000); } if (audioTrack) { // Seek the extractor as close as possible aStartTime = seekTime; audioOutput->SeekToTime(&aStartTime); // Read frames until we get less than 50ms ahead. lastTime = aStartTime; while (seekTime - aStartTime > 50000) { if (audioTrack->ReadFrames((char *)adBuffer, &dummy, &mh) != B_OK) break; aStartTime = mh.start_time; if ((dummy == 0) || (aStartTime <= lastTime)) break; lastTime = aStartTime; } } else startTime = system_time() - vStartTime; // Set the current time view->fCurTime = seekTime; seekNeeded = false; } // Handle normal playing mode else { // Get the next video frame, if any if (videoTrack != NULL) { bitmap->LockBits(); status_t err = videoTrack->ReadFrames((char*)bitmap->Bits(), &dummy, &mh); bitmap->UnlockBits(); if (err != B_OK) goto do_reset; if (dummy == 0) goto do_reset; vStartTime = mh.start_time; } // Estimated snoozeTime if (audioTrack != NULL) startTime = audioOutput->TrackTimebase(); if (videoTrack != NULL) snoozeTime = vStartTime - (system_time() - startTime); else snoozeTime = 25000; // Handle timing issues if (snoozeTime > 5000LL) { view->fSnoozing = true; snooze(snoozeTime-1000); view->fSnoozing = false; } else if (snoozeTime < -5000) { numSkippedFrames++; numFramesToSkip++; } // Set the current time if (!scrubbing) { view->fCurTime = system_time() - startTime; if (view->fCurTime < seekTime) view->fCurTime = seekTime; } } // Handle the drawing : no drawing if we need to skip a frame... if (numSkippedFrames > 0) numSkippedFrames--; // If we can't lock the window after 50ms, better to give up for // that frame... else if (window->LockWithTimeout(50000) == B_OK) { if ((videoTrack != NULL) && !view->fUsingOverlay) view->DrawBitmap(bitmap, view->VideoBounds()); view->fMediaBar->SetCurTime(view->fCurTime); window->Unlock(); // In scrub mode, don't scrub more than 10 times a second if (scrubbing) { snoozeTime = (100000LL+lastScrubbing) - system_time(); if (snoozeTime > 4000LL) { view->fSnoozing = true; snooze(snoozeTime-1000LL); view->fSnoozing = false; } lastScrubbing = curScrubbing; } } // Check if we are required to stop. if (acquire_sem_etc(view->fPlaySem, 1, B_TIMEOUT, 0) == B_OK) release_sem(view->fPlaySem); // The MediaView asked us to stop. else { if (audioTrack != NULL) audioOutput->Stop(); goto do_restart; } DEBUG("############ Current frame:%Ld, total frame:%Ld\n", counterTrack->CurrentFrame(), numFrames); } // If we exited the main streaming loop because we are at the end, // then we need to loop. if (counterTrack->CurrentFrame() >= numFrames) { do_reset: if (audioTrack != NULL) audioOutput->Stop(); seekNeeded = true; seekTime = 0LL; scrubbing = true; } do_restart:; } return (B_NO_ERROR); }
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; }
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; }