void BleFileSource::run()
{
    BleAssert(!m_fileName.isEmpty());

    // m_fileName = "rtsp://218.204.223.237:554/live/1/0547424F573B085C/gsfp90ef4k0a6iap.sdp";
    CvCapture* capture = cvCreateFileCapture(m_fileName.toStdString().c_str());
    BleAssert(capture);

    IplImage* frame;
    while(!m_stop)
    {
        QElapsedTimer elapsedTimer;
        elapsedTimer.start();

        frame = cvQueryFrame(capture);
        if(!frame) break ;

        m_modifyMutex.lock();           // start lock

        BleImage be;
        be.width = frame->width;
        be.height = frame->height;

        be.data = new char[frame->imageSize];
        memcpy(be.data, frame->imageData, frame->imageSize);

        be.dataSize = frame->imageSize;
        be.format = BleImage_Format_BGR24;

        m_image = be;

        m_modifyMutex.unlock();        // end unlock

        int elapsedMs = elapsedTimer.elapsed();
        int needSleepMs = m_interval - elapsedMs;
        if (needSleepMs < 0) {
            needSleepMs = 0;
        }
        msleep(needSleepMs);
    }
    cvReleaseCapture(&capture);

    log_trace("BleFileSource Thread exit normally.");
}
int BleAudioCapture::startCapture(int bitrate, int sampleRate, int channels, int deviceID)
{
    m_bitrate = bitrate;
    m_sampleRate = sampleRate;
    m_channels = channels;

    QString audioFormat = MOption::instance()->option("format", "audio").toString();
    if (audioFormat == "AAC") {
        m_audioEncoder = new BleAudioEncoder_AAC;
    } else if (audioFormat == "MP3") {
        // TODO impl
    }
    BleAssert(m_audioEncoder);

    if (!m_audioEncoder->init(m_sampleRate, m_channels, m_bitrate)) {
        log_error("audio encoder error");
        return BLE_AUDIO_INIT_ERROR;
    }

    m_grabEngine = new RtAudio;

    unsigned int bufferFrames = 2048;
    RtAudio::StreamParameters params;

    if (deviceID == -1) {
        deviceID = m_grabEngine->getDefaultInputDevice();
    }
    params.deviceId = deviceID;
    params.nChannels = m_channels;
    params.firstChannel = 0;

    try {
        m_grabEngine->openStream(NULL, &params, m_bitDepth, m_sampleRate, &bufferFrames, &handleAudioData, this);
        m_grabEngine->startStream();
    } catch (RtError& e) {
        e.printMessage();
        BleFree(m_grabEngine);

        return BLE_AUDIO_DEVICE_OPEN_ERROR;
    }

    BleAVQueue::instance()->timestampBuilder()->
            setAudioCaptureInternal(m_audioEncoder->getFrameDuration());

    start();

    return BLE_SUCESS;
}
void BleEncoderThread::run()
{
    BleImageProcessThread * imageProcessThread = dynamic_cast<BleImageProcessThread *> (m_imageProcessThread);
    BleAssert(imageProcessThread);

    while (!m_stop) {
        QQueue<BleImage*> images = BleAVContext::instance()->captureThread->getQueue();

        // if can't get image, then sleep 50 ms.
        if (images.isEmpty()) {
            msleep(5);
            continue;
        }

        while (!images.empty()) {
            BleImage * image = images.dequeue();
            BleAutoFree(BleImage, image);

            if (image->dataSize <= 0) continue;

            IplImage* imgYUV = cvCreateImage(cvSize(image->width, image->height * 3 / 2), IPL_DEPTH_8U, 1);
            IplImage *cvImage = cvCreateImageHeader(cvSize(image->width, image->height), IPL_DEPTH_8U, 3);
            cvImage->imageData = image->data;
            cvImage->imageDataOrigin = image->data;

            cvCvtColor(cvImage, imgYUV, CV_BGR2YUV_I420);

            m_x264Encoder->encode((uchar*)imgYUV->imageData, image->pts, image->opaque);

            cvReleaseImageHeader(&cvImage);
            cvReleaseImage(&imgYUV);

            if (m_stop) break;
        }

        // do clean
        for (int i = 0; i > images.size(); ++i) {
            BleImage *img = images.at(i);
            BleFree(img);
        }
    }

    log_trace("BleEncoderThread exit normally.");
}
Exemplo n.º 4
0
void BleMainWindow::onEncodeStart()
{
//    m_imageProcessThread = new BleImageProcessThread(this);
//    m_imageProcessWidget->setProcessThread(m_imageProcessThread);

//    QSize si = MOption::instance()->option("res", "encoder").toSize();
//    int fps = MOption::instance()->option("fps", "encoder").toInt();
//    m_imageProcessThread->setResolution(si.width(), si.height());
//    m_imageProcessThread->setInternal(1000 / fps);

    m_encoderThread = new BleEncoderThread(this);
    m_encoderThread->init();

    m_audioCaptureThread = new BleAudioCapture;

    int audioSampleRate = MOption::instance()->option("sample_rate", "audio").toInt();

    int audioChannels = -1;
    QString audioChannelsStr = MOption::instance()->option("channels", "audio").toString();
    if (audioChannelsStr == "Mono") {
        audioChannels = 1;
    } else if (audioChannelsStr == "Stereo") {
        audioChannels = 2;
    }
    BleAssert(audioChannels != -1);

    int audioBitrate = MOption::instance()->option("bitrate", "audio").toInt() * 1000;
    int devID = MOption::instance()->option("dev_id", "audio").toInt();

    int ret = m_audioCaptureThread->startCapture(audioBitrate, audioSampleRate, audioChannels, devID);
    if (ret != BLE_SUCESS) {
        QjtMessageBox::critical(this, tr("error"), tr("start audio capture error."));
    }

    if (!m_sendThread) {
        m_sendThread = new BleRtmpSendThread(this);
        connect(m_sendThread, SIGNAL(status(int,int,int,qint64))
                , this, SLOT(onStatus(int,int,int,qint64)));

        START_THREAD(m_sendThread);
    }
int BleX264Encoder::encode(unsigned char *rgbframe, mint64 pts, void *opaque)
{
    Q_UNUSED(pts);
    unsigned char *src_buf = rgbframe;
    x264_picture_init(m_pictureIn);

    m_pictureIn->img.i_csp = X264_CSP_I420;
    m_pictureIn->img.i_plane = 3;
    m_pictureIn->i_type = X264_TYPE_AUTO;
    m_pictureIn->i_qpplus1 = 0;

    // @note why i_pts plus 1 everytime
    // because the timebase set as above.
    m_pictureIn->i_pts = ++m_encoded_frames;
    m_pictureIn->opaque = opaque;

    m_pictureIn->img.plane[0] = src_buf;
    m_pictureIn->img.plane[1] = src_buf + m_x264Param->i_height * m_x264Param->i_width;
    m_pictureIn->img.plane[2] = src_buf + m_x264Param->i_height * m_x264Param->i_width * 5 / 4;
    m_pictureIn->img.i_stride[0] = m_x264Param->i_width;
    m_pictureIn->img.i_stride[1] = m_x264Param->i_width >> 1;
    m_pictureIn->img.i_stride[2] = m_x264Param->i_width >> 1;

    x264_picture_t picOut;
    int nalNum;
    x264_nal_t* nalOut;
    int len = x264_encoder_encode(m_x264Encoder, &nalOut, &nalNum, m_pictureIn, &picOut);
    if (len < 0) {
        log_error("x264 encode failed");
        return -1;
    }

    if (nalNum <= 0) {
        log_warn("frame delayed in encoder.");
        return -2;
    }

    if(!bFirstFrameProcessed && nalNum)
    {
        if(picOut.i_dts < 0)
            delayOffset = int(-picOut.i_dts);

        bFirstFrameProcessed = true;
    }

    float timeOffset = float(picOut.i_pts - picOut.i_dts) * BleAVQueue::instance()->timestampBuilder()->videoInternal();

    BleVideoPacket *pkt = dynamic_cast<BleVideoPacket *> (BleAVQueue::instance()->find_unencoded_video());
    BleAssert(pkt != NULL);

    MStream &body = pkt->data;
    unsigned char frameType;
    if (IS_X264_TYPE_I(picOut.i_type)) {
        frameType = 0x17;
    } else {
        frameType = 0x27;
    }

    body.write1Bytes(frameType);
    body.write1Bytes(0x01);
    body.write3Bytes((int)timeOffset);

    // NALU payload : 4bytes size + payload
    // NALU payload size : 4bytes size + payload size
    // for b_repeat_headers = 0 in x264_param_t
    // so NALU type is only IDR, SLICE(P or B frame)
    // so you must get SPS PPS before encoding any frame.
    for (int i = 0; i < nalNum; ++i) {
        x264_nal_t &nal = nalOut[i];
        body.writeString((char*)nal.p_payload, nal.i_payload);
    }

    if (IS_X264_TYPE_I(picOut.i_type)) {
        log_trace("I");
    } else if (IS_X264_TYPE_B(picOut.i_type)) {
        log_trace("B");
    } else {
        log_trace("P");
    }

    BleAVQueue::instance()->update_packet(pkt);

    return 0;
}