MediaRecorder* MediaRecorder::create(ExecutionContext* context, MediaStream* stream, const MediaRecorderOptions& options, ExceptionState& exceptionState) { MediaRecorder* recorder = new MediaRecorder(context, stream, options, exceptionState); recorder->suspendIfNeeded(); return recorder; }
/* * End recording (called in a thread) */ void MediaRecorder::EndRecordingThread(void *data) { nsresult rv; PRUint32 wr; MediaRecorder *mr = static_cast<MediaRecorder*>(data); if (mr->v_rec) { rv = mr->vState->backend->StopRecording(); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "could not stop video recording" )); return; } } if (mr->a_rec) { rv = mr->aState->backend->Stop(); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "could not stop audio recording" )); return; } } /* Wait for encoder to finish */ if (mr->v_rec) { mr->v_stp = PR_TRUE; mr->vState->vPipeOut->Close(); } if (mr->a_rec) { mr->a_stp = PR_TRUE; mr->aState->aPipeOut->Close(); } PR_JoinThread(mr->thread); if (mr->v_rec) { mr->vState->vPipeIn->Close(); th_encode_free(mr->vState->th); /* Video trailer */ if (ogg_stream_flush(&mr->vState->os, &mr->vState->og)) { rv = mr->WriteData( mr->vState->og.header, mr->vState->og.header_len, &wr ); rv = mr->WriteData( mr->vState->og.body, mr->vState->og.body_len, &wr ); } ogg_stream_clear(&mr->vState->os); mr->v_rec = PR_FALSE; } if (mr->a_rec) { mr->aState->aPipeIn->Close(); /* Audio trailer */ vorbis_analysis_wrote(&mr->aState->vd, 0); mr->WriteAudio(); vorbis_block_clear(&mr->aState->vb); vorbis_dsp_clear(&mr->aState->vd); vorbis_comment_clear(&mr->aState->vc); vorbis_info_clear(&mr->aState->vi); ogg_stream_clear(&mr->aState->os); mr->a_rec = PR_FALSE; } /* GG */ mr->pipeStream->Close(); NS_DispatchToMainThread(new MediaCallback( mr->observer, "record-ended", "" )); return; }
void MediaRecorder::BeginRecordingThread(void *data) { nsresult rv; MediaRecorder *mr = static_cast<MediaRecorder*>(data); /* Get ready for video! */ if (mr->params->video) { mr->SetupTheoraBOS(); rv = mr->MakePipe( getter_AddRefs(mr->vState->vPipeIn), getter_AddRefs(mr->vState->vPipeOut) ); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "internal: could not create video pipe" )); return; } } /* Get ready for audio! */ if (mr->params->audio) { mr->SetupVorbisBOS(); rv = mr->MakePipe( getter_AddRefs(mr->aState->aPipeIn), getter_AddRefs(mr->aState->aPipeOut) ); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "internal: could not create audio pipe" )); return; } } if (mr->params->video) { mr->v_rec = PR_TRUE; mr->v_stp = PR_FALSE; mr->SetupTheoraHeaders(); mr->vState->backend->StartRecording(mr->vState->vPipeOut); } if (mr->params->audio) { mr->SetupVorbisHeaders(); rv = mr->aState->backend->Start(mr->aState->aPipeOut); if (NS_FAILED(rv)) { /* FIXME: Stop and clean up video! */ NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "internal: could not start audio recording" )); return; } mr->a_rec = PR_TRUE; mr->a_stp = PR_FALSE; } /* Start off encoder after notifying observer */ NS_DispatchToMainThread(new MediaCallback( mr->observer, "record-began", "" )); mr->Encode(); }
/* * Start recording (called in a thread) */ void MediaRecorder::Record(void *data) { nsresult rv; MediaRecorder *mr = static_cast<MediaRecorder*>(data); Properties *params = mr->params; if (mr->a_rec || mr->v_rec) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "recording already in progress" )); return; } /* Setup backends */ #ifdef RAINBOW_Mac mr->aState->backend = new AudioSourceMac(params->chan, params->rate); mr->vState->backend = new VideoSourceMac(params->width, params->height); #endif #ifdef RAINBOW_Win mr->aState->backend = new AudioSourceWin(params->chan, params->rate); mr->vState->backend = new VideoSourceWin(params->width, params->height); #endif #ifdef RAINBOW_Nix mr->aState->backend = new AudioSourceNix(params->chan, params->rate); mr->vState->backend = new VideoSourceNix(params->width, params->height); #endif /* Is the given canvas source or destination? */ if (params->canvas) { mr->vState->backend = new VideoSourceCanvas(params->width, params->height); } /* Update parameters. What we asked for were just hints, * may not end up the same */ params->fps_n = mr->vState->backend->GetFPSN(); params->fps_d = mr->vState->backend->GetFPSD(); params->rate = mr->aState->backend->GetRate(); params->chan = mr->aState->backend->GetChannels(); /* FIXME: device detection TBD */ if (params->audio && (mr->aState == nsnull)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "audio requested but no devices found" )); return; } if (params->video && (mr->vState == nsnull)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "video requested but no devices found" )); return; } /* Get ready for video! */ if (params->video) { mr->SetupTheoraBOS(); rv = mr->MakePipe( getter_AddRefs(mr->vState->vPipeIn), getter_AddRefs(mr->vState->vPipeOut) ); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "internal: could not create video pipe" )); return; } } /* Get ready for audio! */ if (params->audio) { mr->SetupVorbisBOS(); rv = mr->MakePipe( getter_AddRefs(mr->aState->aPipeIn), getter_AddRefs(mr->aState->aPipeOut) ); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "internal: could not create audio pipe" )); return; } } /* Let's DO this. */ if (params->video) { mr->SetupTheoraHeaders(); rv = mr->vState->backend->Start(mr->vState->vPipeOut, mr->canvas); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "internal: could not start video recording" )); return; } mr->v_rec = PR_TRUE; mr->v_stp = PR_FALSE; } if (params->audio) { mr->SetupVorbisHeaders(); rv = mr->aState->backend->Start(mr->aState->aPipeOut); if (NS_FAILED(rv)) { /* FIXME: Stop and clean up video! */ NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "internal: could not start audio recording" )); return; } mr->a_rec = PR_TRUE; mr->a_stp = PR_FALSE; } /* Start off encoder after notifying observer */ NS_DispatchToMainThread(new MediaCallback( mr->observer, "started", "" )); mr->Encode(); return; }