int BleRtmpSendThread::service(BleRtmpMuxer & muxer)
{
    int ret = BLE_SUCESS;

    if ((ret = sendVideoSh(muxer)) != BLE_SUCESS) {
        return ret;
    }

    if ((ret = sendAudioSh(muxer)) != BLE_SUCESS) {
        return ret;
    }

    while (!m_stop) {
        QQueue<BleAVPacket *> pkts = BleAVQueue::instance()->dequeue();
        if (pkts.isEmpty()) {
            msleep(50);
            continue;
        }

        BleAutoLocker(m_mutex);

        while (!pkts.empty()) {
            BleAVPacket *pkt = pkts.dequeue();
            BleAutoFree(BleAVPacket, pkt);

            MStream &data = pkt->data;

            if (pkt->pktType == Packet_Type_Video) {
                if (muxer.addH264(data, pkt->dts) != TRUE ) {
                    ret = BLE_RTMPSEND_ERROR;
                    break;
                }

                m_videoKbps += (data.size() + 11);
                m_fps += 1;
            } else if (pkt->pktType == Packet_Type_Audio) {
                if (muxer.addAAC(data, pkt->dts) != TRUE ) {
                    ret = BLE_RTMPSEND_ERROR;
                    break;
                }

                m_audioKbps += (data.size() + 11);
            }

            m_sendDataCount += (data.size() + 11);
        }

        // if send failed, then pkts may has some pkt
        // we should delete it.
        for (int i = 0; i < pkts.size(); ++i) {
            BleAVPacket *pkt = pkts.at(i);
            BleFree(pkt);
        }
    }

    return ret;
}
void BleRtmpSendThread::run()
{
#ifdef Q_OS_WIN
    if (wsaStart()) {
        return;
    }
#endif

    int ret = BLE_SUCESS;
    while (!m_stop) {
        QString url = MOption::instance()->option("address", "network").toString();
        if (url.isEmpty()) {
            log_error("no url was set, please input your rtmp url !");
            sleep(5);
            continue;
        }

        BleRtmpMuxer *muxer = new BleRtmpMuxer;
        BleAutoFree(BleRtmpMuxer, muxer);

        muxer->setRtmpUrl(url.toStdString());
        ret = muxer->start();
        if (ret != TRUE) {
            ret = BLE_RTMPCONNECT_ERROR;
            log_error("connect to %s error, after 3s to retry", url.toStdString().c_str());

            muxer->stop();
            sleep(3);

            continue;
        }

        log_trace("connect to %s success.", url.toStdString().c_str());
        ret = service(*muxer);
        muxer->stop();

        if (ret != BLE_SUCESS) {
            log_error("rtmp send error, ret = %d", ret);
            continue;
        }
    }

#ifdef Q_OS_WIN
    WSACleanup();
#endif

    log_trace("Ble RtmpSendThread exit normally.");
}
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.");
}