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, ¶ms, 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."); }
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; }