예제 #1
0
MediaRecorder* MediaRecorder::create(ExecutionContext* context, MediaStream* stream,  const MediaRecorderOptions& options, ExceptionState& exceptionState)
{
    MediaRecorder* recorder = new MediaRecorder(context, stream, options, exceptionState);
    recorder->suspendIfNeeded();

    return recorder;
}
예제 #2
0
/*
 * 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;
}
예제 #3
0
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();
}
예제 #4
0
/*
 * 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;
}