提交 efc1d748 authored 作者: autulin's avatar autulin

Merge remote-tracking branch 'origin/master'

# Conflicts: # gb28181library/src/main/cpp/gb28181_muxer.cpp # gb28181library/src/main/cpp/gb28181_muxer.h # gb28181library/src/main/java/com/autulin/gb28181library/DemoActivity.java
......@@ -13,6 +13,11 @@ android {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
// 指定ndk编译的平台
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
externalNativeBuild {
cmake {
cppFlags "-std=c++14"
......
......@@ -46,15 +46,15 @@ void *GB28181_sender::processSend(void *obj) {
uint16_t len = bytes2short(pkt_buf);
uint64_t t1 = getCurrentTime();
// char strBuf[16];
// sprintf(strBuf, "get pkt len: %d", len);
int n;
ssize_t n;
switch (gb28181Sender->args->outType) {
case 0: // udp
n = gb28181Sender->sendData(pkt_buf + 2, len);
LOGE("[sender]get pkt len: %d. sent %d. (queue left size: %d)", len, n, gb28181Sender->pkt_queue.size());
LOGI("[sender][udp]get pkt len: %d. sent %ld. (queue left size: %d)", len, n, gb28181Sender->pkt_queue.size());
break;
case 1: // tcp
n = gb28181Sender->sendData(pkt_buf, len + 2);
LOGI("[sender][tcp]get pkt len: %d. sent %ld. (queue left size: %d)", len, n, gb28181Sender->pkt_queue.size());
break;
case 2: // file
gb28181Sender->fout.write((const char *) (pkt_buf + 2), len);
......@@ -104,13 +104,23 @@ int GB28181_sender::closeSender() {
}
int GB28181_sender::initSocket(char *hostname, int port) {
//todo
switch (args->outType) {
case 0: // udp
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
break;
case 1: // tcp
sockfd = socket(AF_INET, SOCK_STREAM, 0);
break;
default:
sockfd = -99;
}
if (sockfd < 0){
LOGE("ERROR opening socket");
LOGE("ERROR opening socket.(%d)", sockfd);
return sockfd;
}
// 域名解析相关
// struct hostent *server;
// server = gethostbyname(hostname);
// if (server == NULL) {
......@@ -127,11 +137,32 @@ int GB28181_sender::initSocket(char *hostname, int port) {
serveraddr.sin_port = htons(port);
serverlen = sizeof(serveraddr);
if (args->outType == 1) { // tcp
int ret = connect(sockfd, (const sockaddr *) &serveraddr, serverlen);
if (ret < 0){
LOGE("ERROR connect.(%d)", ret);
return ret;
}
}
return 0;
}
int GB28181_sender::sendData(uint8_t *buf, int len) {
int n = sendto(sockfd, buf, len, 0, (const sockaddr *) &serveraddr, serverlen);
ssize_t GB28181_sender::sendData(uint8_t *buf, int len) {
ssize_t n = 0;
switch (args->outType) {
case 0: // udp
n = sendto(sockfd, buf, len, 0, (const sockaddr *) &serveraddr, serverlen);
break;
case 1: // tcp
n = send(sockfd, buf, len, 0);
break;
default:
return -1;
}
if (n < 0) {
LOGE("send error.(%ld)", n);
}
return n;
}
......
......@@ -47,7 +47,7 @@ private:
int serverlen;
int initSocket(char* hostname, int port);
int sendData(uint8_t * buf, int len);
ssize_t sendData(uint8_t * buf, int len);
int closeSocket();
......
......@@ -59,7 +59,7 @@ int GB28181Muxer::initMuxer() {
pCodecCtx->bit_rate = arguments->video_bit_rate;
//这里是设置关键帧的间隔
pCodecCtx->gop_size = 25;
pCodecCtx->thread_count = 12;
pCodecCtx->thread_count = 3;
pCodecCtx->time_base.num = 1;
pCodecCtx->time_base.den = arguments->video_frame_rate;
......@@ -98,21 +98,23 @@ int GB28181Muxer::initMuxer() {
gb28181Sender = new GB28181_sender(arguments);
gb28181Sender->initSender();
pFrame = av_frame_alloc();
in_y_size = arguments->in_width * arguments->in_height;
picture_size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
LOGI(" picture_size:%d", picture_size);
uint8_t *buf = (uint8_t *) av_malloc(picture_size);
avpicture_fill((AVPicture *) pFrame, buf, pCodecCtx->pix_fmt, pCodecCtx->width,
pCodecCtx->height);
av_new_packet(&pkt, picture_size);
av_new_packet(&nPkt, picture_size);
nextPkt = &nPkt;
g711aFrameLen = arguments->a_frame_len / 2;
scrPerFrame = 90000 / arguments->video_frame_rate;
out_y_size = pCodecCtx->width * pCodecCtx->height;
is_end = START_STATE;
pthread_t thread;
pthread_create(&thread, NULL, GB28181Muxer::startMux, this);
pthread_t thread2;
pthread_create(&thread2, NULL, GB28181Muxer::startEncode, this);
LOGI("视频编码器初始化完成")
return 0;
......@@ -124,17 +126,34 @@ int GB28181Muxer::initMuxer() {
* @return
*/
int GB28181Muxer::sendVideoFrame(uint8_t *buf) {
int in_y_size = arguments->in_width * arguments->in_height;
int64_t st = getCurrentTime();
AVFrame *pNewFrame = genFrame(buf);
int64_t st1 = getCurrentTime();
vFrame_queue.push(pNewFrame);
int64_t et = getCurrentTime();
LOGE("生成帧用时:%lld, 原始帧入队用时:%lld", st1 - st, et - st1);
videoFrameCnt++;
return 0;
}
AVFrame *GB28181Muxer::genFrame(uint8_t *rawData) {
uint8_t *new_buf = (uint8_t *) malloc(in_y_size * 3 / 2);
memcpy(new_buf, buf, in_y_size * 3 / 2);
video_queue.push(new_buf);
int64_t nowPushTime = getCurrentTime();
LOGI("[muxer]推入帧间隔时间:%lld", nowPushTime - lastPushTime);
lastPushTime = nowPushTime;
memcpy(new_buf, rawData, in_y_size * 3 / 2);
return 0;
AVFrame *pNewFrame = av_frame_alloc();
uint8_t *buf = (uint8_t *) av_malloc(picture_size);
avpicture_fill((AVPicture *) pNewFrame, buf, pCodecCtx->pix_fmt, pCodecCtx->width,
pCodecCtx->height);
custom_filter(this, new_buf, pNewFrame);
if (startTime == 0) {
startTime = getCurrentTime();
pNewFrame->pts = 0;
} else {
pNewFrame->pts = (getCurrentTime() - startTime) * 90;
}
LOGI("new Frame pts:%lld(%d)",
pNewFrame->pts, videoFrameCnt);
return pNewFrame;
}
/**
......@@ -155,6 +174,28 @@ int GB28181Muxer::sendAudioFrame(uint8_t *buf) {
return 0;
}
void *GB28181Muxer::startEncode(void *obj) {
LOGE("start encode thread");
GB28181Muxer *gb28181Muxer = (GB28181Muxer *) obj;
while (!gb28181Muxer->is_end) {
int64_t st = getCurrentTime();
AVFrame * pFrame = *gb28181Muxer->vFrame_queue.wait_and_pop();
int64_t et1 = getCurrentTime();
int ret = avcodec_send_frame(gb28181Muxer->pCodecCtx, pFrame);
while (ret == AVERROR(EAGAIN)) {
// LOGE("送入FFmpeg错误:%d.(重试)", ret);
usleep(5000);
ret = avcodec_send_frame(gb28181Muxer->pCodecCtx, pFrame);
}
int64_t et2 = getCurrentTime();
LOGE("fetch queue time:%lld(frame left:%d),in FFmpeg time:%lld.", et1 - st, gb28181Muxer->vFrame_queue.size(), et2 - et1);
if (ret < 0) {
LOGE("send FFmpeg error:%d.", ret);
}
}
}
/**
* 启动编码线程
* @param obj
......@@ -164,40 +205,34 @@ void *GB28181Muxer::startMux(void *obj) {
LOGE("start mux thread");
GB28181Muxer *gb28181Muxer = (GB28181Muxer *) obj;
while (!gb28181Muxer->is_end) {
if (gb28181Muxer->video_queue.empty()) {
continue;
}
uint8_t *picture_buf = *gb28181Muxer->video_queue.wait_and_pop().get();
int64_t v_time = bytes2long(picture_buf);
int in_y_size = gb28181Muxer->arguments->in_width * gb28181Muxer->arguments->in_height;
// 处理视频帧并到 h264_encoder->pFrame 中
gb28181Muxer->custom_filter(gb28181Muxer, picture_buf + 8, in_y_size,
gb28181Muxer->arguments->v_custom_format);
delete (picture_buf);
int64_t lastPTS = gb28181Muxer->pFrame->pts;
if (gb28181Muxer->startTime == 0) gb28181Muxer->startTime = v_time;
gb28181Muxer->pFrame->pts = (v_time - gb28181Muxer->startTime) * 90;
LOGE("v_time:%lld,startTime: %lld, now:%lld, lastPTS: %lld, new PTS: %lld, divid: %lld",
v_time,
gb28181Muxer->startTime, getCurrentTime(), lastPTS, gb28181Muxer->pFrame->pts,
gb28181Muxer->pFrame->pts - lastPTS);
gb28181Muxer->videoFrameCnt++;
int got_picture = 0;
//Encode
int ret = avcodec_encode_video2(gb28181Muxer->pCodecCtx, &gb28181Muxer->pkt,
gb28181Muxer->pFrame, &got_picture);
int ret;
int64_t st = getCurrentTime();
if (gb28181Muxer->muxCnt == 0) { // 获得首帧
ret = avcodec_receive_packet(gb28181Muxer->pCodecCtx, &gb28181Muxer->pkt);
if (ret < 0) {
LOGE("Failed to encode! \n");
usleep(5000);
} else{
gb28181Muxer->nowPkt = &gb28181Muxer->pkt;
LOGI("got first encoded pkt!(pts:%lld, queue size: %d) \n",
gb28181Muxer->nowPkt->pts, gb28181Muxer->video_queue.size());
gb28181Muxer->lastPts = gb28181Muxer->nowPkt->pts;
gb28181Muxer->muxCnt++;
}
// 前几次调用avcodec_encode_video2可能是拿不到编码好的视频的
if (got_picture == 1) {
} else {
ret = avcodec_receive_packet(gb28181Muxer->pCodecCtx, gb28181Muxer->nextPkt);
if (ret < 0) {
// LOGE("Failed to send encode!(%d) \n", ret);
usleep(5000);
} else {
// LOGI("got encoded pkt!(pts:%lld, queue size: %d) \n", gb28181Muxer->nextPkt->pts,
// gb28181Muxer->video_queue.size());
gb28181Muxer->mux(gb28181Muxer);
}
}
int64_t et = getCurrentTime();
if (ret >= 0)
LOGE("mux one time:%lld", et - st);
}
if (gb28181Muxer->is_end) {
gb28181Muxer->endMux();
delete gb28181Muxer;
......@@ -214,8 +249,9 @@ void *GB28181Muxer::startMux(void *obj) {
*/
void
GB28181Muxer::custom_filter(const GB28181Muxer *gb28181Muxer, const uint8_t *picture_buf,
int in_y_size, int format) {
AVFrame *pFrame) {
int format = arguments->v_custom_format;
// y值在H方向开始行
int y_height_start_index =
gb28181Muxer->arguments->in_height - gb28181Muxer->arguments->out_height;
......@@ -230,7 +266,7 @@ GB28181Muxer::custom_filter(const GB28181Muxer *gb28181Muxer, const uint8_t *pic
int index = gb28181Muxer->arguments->in_width * i + j;
uint8_t value = *(picture_buf + index);
*(gb28181Muxer->pFrame->data[0] + j * gb28181Muxer->arguments->out_height +
*(pFrame->data[0] + j * gb28181Muxer->arguments->out_height +
(gb28181Muxer->arguments->out_height - (i - y_height_start_index) - 1)) = value;
}
}
......@@ -240,11 +276,11 @@ GB28181Muxer::custom_filter(const GB28181Muxer *gb28181Muxer, const uint8_t *pic
int index = gb28181Muxer->arguments->in_width / 2 * i + j;
uint8_t v = *(picture_buf + in_y_size + index);
uint8_t u = *(picture_buf + in_y_size * 5 / 4 + index);
*(gb28181Muxer->pFrame->data[2] + (j * gb28181Muxer->arguments->out_height / 2 +
*(pFrame->data[2] + (j * gb28181Muxer->arguments->out_height / 2 +
(gb28181Muxer->arguments->out_height / 2 -
(i - uv_height_start_index) -
1))) = v;
*(gb28181Muxer->pFrame->data[1] + (j * gb28181Muxer->arguments->out_height / 2 +
*(pFrame->data[1] + (j * gb28181Muxer->arguments->out_height / 2 +
(gb28181Muxer->arguments->out_height / 2 -
(i - uv_height_start_index) -
1))) = u;
......@@ -260,7 +296,7 @@ GB28181Muxer::custom_filter(const GB28181Muxer *gb28181Muxer, const uint8_t *pic
int index = gb28181Muxer->arguments->in_width * i + j;
uint8_t value = *(picture_buf + index);
*(gb28181Muxer->pFrame->data[0] +
*(pFrame->data[0] +
(i - y_height_start_index) * gb28181Muxer->arguments->out_width +
j) = value;
}
......@@ -274,9 +310,9 @@ GB28181Muxer::custom_filter(const GB28181Muxer *gb28181Muxer, const uint8_t *pic
uint8_t v = *(picture_buf + in_y_size + index);
uint8_t u = *(picture_buf + in_y_size * 5 / 4 + index);
*(gb28181Muxer->pFrame->data[2] +
*(pFrame->data[2] +
((i - uv_height_start_index) * gb28181Muxer->arguments->out_width / 2 + j)) = v;
*(gb28181Muxer->pFrame->data[1] +
*(pFrame->data[1] +
((i - uv_height_start_index) * gb28181Muxer->arguments->out_width / 2 + j)) = u;
}
}
......@@ -293,7 +329,7 @@ GB28181Muxer::custom_filter(const GB28181Muxer *gb28181Muxer, const uint8_t *pic
int index = gb28181Muxer->arguments->in_width *
(gb28181Muxer->arguments->out_height - i - 1) + j;
uint8_t value = *(picture_buf + index);
*(gb28181Muxer->pFrame->data[0] +
*(pFrame->data[0] +
(gb28181Muxer->arguments->out_width - (j - y_width_start_index) - 1)
* gb28181Muxer->arguments->out_height +
i) = value;
......@@ -305,11 +341,11 @@ GB28181Muxer::custom_filter(const GB28181Muxer *gb28181Muxer, const uint8_t *pic
(gb28181Muxer->arguments->out_height / 2 - i - 1) + j;
uint8_t v = *(picture_buf + in_y_size + index);
uint8_t u = *(picture_buf + in_y_size * 5 / 4 + index);
*(gb28181Muxer->pFrame->data[2] +
*(pFrame->data[2] +
(gb28181Muxer->arguments->out_width / 2 - (j - uv_width_start_index) - 1)
* gb28181Muxer->arguments->out_height / 2 +
i) = v;
*(gb28181Muxer->pFrame->data[1] +
*(pFrame->data[1] +
(gb28181Muxer->arguments->out_width / 2 - (j - uv_width_start_index) - 1)
* gb28181Muxer->arguments->out_height / 2 +
i) = u;
......@@ -334,7 +370,7 @@ int GB28181Muxer::endMux() {
//Clean
if (video_st) {
avcodec_close(video_st->codec);
av_free(pFrame);
// av_free(pFrame);
// av_free(picture_buf);
}
// avio_close(pFormatCtx->pb);
......@@ -353,127 +389,83 @@ void GB28181Muxer::user_end() {
}
int GB28181Muxer::mux(GB28181Muxer *gb28181Muxer) {
int64_t lastPts = gb28181Muxer->pkt.pts;
gb28181Muxer->nowPkt = &gb28181Muxer->pkt;
int64_t append = 0;
int cnt = 0;
int aFrameLen = gb28181Muxer->arguments->a_frame_len / 2;
while (!gb28181Muxer->is_end) {
char szTempPacketHead[256];
//init header buffer
char gb28181headerBuf[256];
int nSizePos = 0;
int nSize = 0;
memset(szTempPacketHead, 0, 256);
uint64_t start_t = getCurrentTime();
// read next frame
uint8_t *picture_buf = *gb28181Muxer->video_queue.wait_and_pop().get();
uint64_t t1 = getCurrentTime();
// 视频输入格式转换,变成pkt
int64_t v_time = bytes2long(picture_buf);
int in_y_size = gb28181Muxer->arguments->in_width * gb28181Muxer->arguments->in_height;
gb28181Muxer->custom_filter(gb28181Muxer, picture_buf + 8, in_y_size,
gb28181Muxer->arguments->v_custom_format);
delete (picture_buf);
memset(gb28181headerBuf, 0, 256);
uint64_t t2 = getCurrentTime();
gb28181Muxer->pFrame->pts = (v_time - gb28181Muxer->startTime) * 90;
LOGE("v_time: %lld, get a pts:%lld (audio queue left num: %d, video queue left num: %d, count: %d)",
v_time, gb28181Muxer->pFrame->pts, audio_queue.size(), video_queue.size(), gb28181Muxer->videoFrameCnt++);
int got_picture;
// 送入编码器
int ret = avcodec_encode_video2(gb28181Muxer->pCodecCtx, gb28181Muxer->nextPkt,
gb28181Muxer->pFrame, &got_picture);
if (ret < 0) {
LOGE("Failed to encode!11111111111111 \n");
}
uint64_t t3 = getCurrentTime();
// 读到了下一帧
int64_t newPts = gb28181Muxer->nextPkt->pts;
// 计算写入音频的个数
int64_t frameDiv = newPts - lastPts;
append = (frameDiv + append) % 3600;
int audioCnt = (frameDiv + append) / 3600;
// LOGE("now pts:%lld.|%lld| next pts:%lld,audio count:%d",
// gb28181Muxer->nowPkt->pts,
// gb28181Muxer->nextPkt->pts - gb28181Muxer->nowPkt->pts,
// gb28181Muxer->nextPkt->pts, audioCnt);
int64_t frameDiv = newPts - gb28181Muxer->lastPts;
gb28181Muxer->frameAppend = (frameDiv + gb28181Muxer->frameAppend) % 3600;
int audioCnt = (frameDiv + gb28181Muxer->frameAppend) / 3600;
LOGI("now pts:%lld.|%lld| next pts:%lld,audio count:%d",
gb28181Muxer->nowPkt->pts,
gb28181Muxer->nextPkt->pts - gb28181Muxer->nowPkt->pts,
gb28181Muxer->nextPkt->pts, audioCnt);
// 0 rtp header
gb28181_make_rtp_header(szTempPacketHead + nSizePos, cnt++, lastPts, 1, RTP_PKT_END);
gb28181_make_rtp_header(gb28181headerBuf + nSizePos, gb28181Muxer->muxCnt++,
gb28181Muxer->lastPts, gb28181Muxer->arguments->ssrc, RTP_PKT_END);
nSizePos += RTP_HDR_LEN;
// 1 package for ps header
gb28181_make_ps_header(szTempPacketHead + nSizePos, lastPts);
gb28181_make_ps_header(gb28181headerBuf + nSizePos, gb28181Muxer->lastPts);
nSizePos += PS_HDR_LEN;
//2 system header
if (gb28181Muxer->nowPkt->flags == 1) {
// 如果是I帧的话,则添加系统头
gb28181_make_sys_header(szTempPacketHead + nSizePos, audioCnt);
gb28181_make_sys_header(gb28181headerBuf + nSizePos, audioCnt);
nSizePos += SYS_HDR_LEN;
gb28181_make_psm_header(szTempPacketHead + nSizePos);
gb28181_make_psm_header(gb28181headerBuf + nSizePos);
nSizePos += PSM_HDR_LEN;
}
nSize = gb28181Muxer->nowPkt->size;
// video psm
gb28181_make_pes_header(szTempPacketHead + nSizePos, 0xE0, nSize, lastPts, lastPts);
gb28181_make_pes_header(gb28181headerBuf + nSizePos, 0xE0, nSize, gb28181Muxer->lastPts,
gb28181Muxer->lastPts);
nSizePos += PES_HDR_LEN;
// gb28181Muxer->fout.write(szTempPacketHead, nSizePos);
// gb28181Muxer->fout.write(reinterpret_cast<const char *>(gb28181Muxer->nowPkt->data), nSize);
lastPts = gb28181Muxer->nextPkt->pts;
gb28181Muxer->lastPts = gb28181Muxer->nextPkt->pts;
uint16_t pktPos = 0;
uint16_t pkt_len = (uint16_t) (nSizePos + nSize + audioCnt * (PES_HDR_LEN + aFrameLen));
// LOGE("pkt_len in muxer: %d", pkt_len);
uint16_t pkt_len = (uint16_t) (nSizePos + nSize +
audioCnt * (PES_HDR_LEN + gb28181Muxer->g711aFrameLen));
uint8_t *pkt_full = (uint8_t *) malloc(pkt_len + 2);
memcpy(pkt_full, short2Bytes(pkt_len), 2);
pktPos += 2;
memcpy(pkt_full + pktPos, szTempPacketHead, nSizePos);
memcpy(pkt_full + pktPos, gb28181headerBuf, nSizePos);
pktPos += nSizePos;
memcpy(pkt_full + pktPos, gb28181Muxer->nowPkt->data, nSize);
pktPos+= nSize;
pktPos += nSize;
// LOGE("orgin frame:%ld", h264_encoder->nowPkt->pts);
// next packet
gb28181Muxer->nowPkt->stream_index = gb28181Muxer->video_st->index;
AVPacket *t = gb28181Muxer->nowPkt;
av_free_packet(gb28181Muxer->nowPkt);
gb28181Muxer->nowPkt = gb28181Muxer->nextPkt;
gb28181Muxer->nextPkt = t;
// LOGE("now frame:%ld", h264_encoder->nowPkt->pts);
uint64_t t4 = getCurrentTime();
// audio part
while (audioCnt > 0) {
uint8_t *audioFrame = *gb28181Muxer->audio_queue.wait_and_pop().get();
int64_t audioPts = gb28181Muxer->audioFrameCnt * 3600; // 音频默认25帧,90000/25=3600
gb28181_make_pes_header(szTempPacketHead + nSizePos, 0xC0, aFrameLen, audioPts,
gb28181_make_pes_header(gb28181headerBuf + nSizePos, 0xC0, gb28181Muxer->g711aFrameLen,
audioPts,
audioPts);
memcpy(pkt_full + pktPos, szTempPacketHead + nSizePos, PES_HDR_LEN);
pktPos+=PES_HDR_LEN;
// fout.write(szTempPacketHead + nSizePos, PES_HDR_LEN);
memcpy(pkt_full + pktPos, gb28181headerBuf + nSizePos, PES_HDR_LEN);
pktPos += PES_HDR_LEN;
nSizePos += PES_HDR_LEN;
memcpy(pkt_full + pktPos, audioFrame, aFrameLen);
pktPos+= aFrameLen;
// fout.write(reinterpret_cast<char *>(audioFrame), aFrameLen);
memcpy(pkt_full + pktPos, audioFrame, gb28181Muxer->g711aFrameLen);
pktPos += gb28181Muxer->g711aFrameLen;
gb28181Muxer->audioFrameCnt++;
audioCnt--;
delete (audioFrame);
}
uint64_t t5 = getCurrentTime();
gb28181Sender->addPkt(pkt_full);
LOGI("[muxer]从队列取:%lld\t格式转换:%lld\t送入编码器:%lld\t视频Header制作:%lld\t音频Header制作:%lld\t",
t1 - start_t,
t2 - t1,
t3 - t2,
t4 - t3,
t5 - t4
)
}
LOGE("mux over!");
LOGI("mux one pkt over!(video queue size: %d, audio queue size: %d)",
gb28181Muxer->video_queue.size(), gb28181Muxer->audio_queue.size());
return 0;
}
\ No newline at end of file
......@@ -21,6 +21,7 @@ public:
int initMuxer();
static void* startMux(void *obj);
static void* startEncode(void *obj);
int sendVideoFrame(uint8_t *buf);
......@@ -31,8 +32,7 @@ public:
int endMux();
void custom_filter(const GB28181Muxer *gb28181Muxer, const uint8_t *picture_buf,
int in_y_size,
int format);
AVFrame *pFrame);
~GB28181Muxer() {
}
......@@ -44,6 +44,7 @@ private:
GB28181_sender *gb28181Sender;
int is_end = START_STATE;
int is_release = RELEASE_FALSE;
threadsafe_queue<AVFrame *> vFrame_queue;
threadsafe_queue<uint8_t *> video_queue;
threadsafe_queue<uint8_t *> audio_queue;
AVFormatContext *pFormatCtx;
......@@ -55,17 +56,22 @@ private:
AVPacket nPkt;
AVPacket *nowPkt;
AVPacket *nextPkt;
AVFrame *pFrame;
int picture_size;
int out_y_size;
int audioFrameCnt = 0;
int videoFrameCnt = 0;
int64_t startTime = 0;
int in_y_size;
int64_t lastPushTime = 0;
//合成相关的参数
int g711aFrameLen = 0;
int64_t lastPts = 0;
int64_t frameAppend = 0;
int scrPerFrame;
int muxCnt = 0;
int mux(GB28181Muxer *gb28181Muxer);
AVFrame * genFrame(uint8_t *rawData);
};
#endif //GB281818_MUXER_H
......@@ -32,7 +32,7 @@ Java_com_autulin_gb28181library_JNIBridge_initMuxer(JNIEnv *env, jclass type, js
jstring mediaBasePath_, jstring mediaName_,
jint filter, jint in_width, jint in_height,
jint out_width, jint out_height, jint frameRate,
jlong bit_rate, jint audioFrameLen) {
jlong bit_rate, jint audioFrameLen, jint ssrc) {
const char *ip = env->GetStringUTFChars(ip_, 0);
const char *mediaBasePath = env->GetStringUTFChars(mediaBasePath_, 0);
const char *mediaName = env->GetStringUTFChars(mediaName_, 0);
......@@ -44,8 +44,7 @@ Java_com_autulin_gb28181library_JNIBridge_initMuxer(JNIEnv *env, jclass type, js
strcpy(arguments->ip_addr, ip);
arguments->port = port;
arguments->outType = outType;
arguments->media_base_path = mediaBasePath;
arguments->media_name = mediaName;
arguments->ssrc = ssrc;
size_t m_path_size = strlen(mediaBasePath) + strlen(mediaName) + strlen(MEDIA_FORMAT) + 1;
arguments->media_path = (char *) malloc(m_path_size + 1);
......
......@@ -9,8 +9,6 @@ typedef struct UserArguments {
char *ip_addr;
int port;
int outType;
const char *media_base_path; //文件储存地址
const char *media_name; // 文件命令前缀
char *media_path; //合成后的MP4储存地址
int in_width; //输出宽度
int in_height; //输入高度
......@@ -20,6 +18,7 @@ typedef struct UserArguments {
int64_t video_bit_rate; //视频比特率控制
int v_custom_format; //一些滤镜操作控制
int a_frame_len;
int ssrc;
JNIEnv *env; //env全局指针
JavaVM *javaVM; //jvm指针
jclass java_class; //java接口类的calss对象
......
......@@ -49,8 +49,14 @@ public class DemoActivity extends AppCompatActivity implements
mMediaRecorder.endMux();
}
}
// new Thread(runnable).start();
}
});
try {
Runtime.getRuntime().exec("logcat -f /sdcard/DCIM/pstest/log.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
......@@ -98,8 +104,9 @@ public class DemoActivity extends AppCompatActivity implements
// 设置输出
// String fileName = String.valueOf(System.currentTimeMillis());
String fileName = "tttttt";
// mediaOutput = mMediaRecorder.setFileOutPut(fileName); //输出到文件,这里demo是/sdcard/DCIM/pstest/tttttt.ps
mediaOutput = mMediaRecorder.setUdpOutPut("10.112.181.160", 8888);
mediaOutput = mMediaRecorder.setFileOutPut(fileName); //输出到文件,这里demo是/sdcard/DCIM/pstest/tttttt.ps
// int ssrc = 1;
// mediaOutput = mMediaRecorder.setUdpOutPut("10.112.181.160", 8888, ssrc);
mMediaRecorder.setSurfaceHolder(mSurfaceView.getHolder());
mMediaRecorder.prepare();
......
......@@ -64,7 +64,8 @@ public class JNIBridge {
int out_height,
int frameRate,
long bit_rate,
int audioFrameLen
int audioFrameLen,
int ssrc
);
public static native int sendOneVideoFrame(byte[] data);
......
......@@ -6,13 +6,15 @@ public class MediaOutput {
private String outputDir;
private String outputName;
private int outputType;
private int ssrc;
public MediaOutput(String ip, int port, String outputDir, String outputName, int outputType) {
public MediaOutput(String ip, int port, String outputDir, String outputName, int outputType, int ssrc) {
this.ip = ip;
this.port = port;
this.outputDir = outputDir;
this.outputName = outputName;
this.outputType = outputType;
this.ssrc = ssrc;
}
public String getIp() {
......@@ -54,4 +56,12 @@ public class MediaOutput {
public void setOutputType(int outputType) {
this.outputType = outputType;
}
public int getSsrc() {
return ssrc;
}
public void setSsrc(int ssrc) {
this.ssrc = ssrc;
}
}
......@@ -712,13 +712,13 @@ public abstract class MediaRecorderBase implements Callback, PreviewCallback, IM
this.mFrameRateCmd= String.format(" -r %d",rate);
}
public MediaOutput setTcpOutPut(String ip, int port) {
mediaOutput = new MediaOutput(ip, port, "", "", JNIBridge.TCP);
public MediaOutput setTcpOutPut(String ip, int port, int ssrc) {
mediaOutput = new MediaOutput(ip, port, "", "", JNIBridge.TCP, ssrc);
return mediaOutput;
}
public MediaOutput setUdpOutPut(String ip, int port) {
mediaOutput = new MediaOutput(ip, port, "", "", JNIBridge.UDP);
public MediaOutput setUdpOutPut(String ip, int port, int ssrc) {
mediaOutput = new MediaOutput(ip, port, "", "", JNIBridge.UDP, ssrc);
return mediaOutput;
}
......@@ -741,7 +741,7 @@ public abstract class MediaRecorderBase implements Callback, PreviewCallback, IM
if (!file.exists()) {
file.mkdirs();
}
mediaOutput = new MediaOutput("", 0, path, fileName, JNIBridge.FILE);
mediaOutput = new MediaOutput("", 0, path, fileName, JNIBridge.FILE, 0);
return mediaOutput;
}
}
......@@ -16,20 +16,17 @@ public class MediaRecorderNative extends MediaRecorderBase implements MediaRecor
JNIBridge.endMux();
}
long t = System.currentTimeMillis();
/**
* 视频数据回调
*/
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (mRecording) {
long t = System.currentTimeMillis();
byte[] mdata = new byte[data.length + 8];
for (int i = 0; i < 8; i++) {
int offset = 64 - (i + 1) * 8;
mdata[i] = (byte) ((t >> offset) & 0xff);
}
System.arraycopy(data, 0, mdata, 8, data.length);
JNIBridge.sendOneVideoFrame(mdata);
long nt = System.currentTimeMillis();
Log.e("now", "onPreviewFrame: "+ nt + ", div:" + (nt- t));
t = nt;
JNIBridge.sendOneVideoFrame(data);
mPreviewFrameCallCount++;
}
super.onPreviewFrame(data, camera);
......@@ -88,7 +85,8 @@ public class MediaRecorderNative extends MediaRecorderBase implements MediaRecor
SMALL_VIDEO_HEIGHT,
mFrameRate,
mVideoBitrate,
mAudioCollector.getFrameLen()
mAudioCollector.getFrameLen(),
mediaOutput.getSsrc()
);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论