提交 589587a8 authored 作者: autulin's avatar autulin

将数据包合并发送到sender的队列中,由sender来进行发送操作

TODO:网络发送的具体实现
上级 83c6bb23
......@@ -20,6 +20,7 @@ add_library( # Sets the name of the library.
src/main/cpp/native-lib.cpp
src/main/cpp/gb28181_muxer.cpp
src/main/cpp/gb28181_sender.cpp
src/main/cpp/threadsafe_queue.cpp
)
......
//
// Created by autulin on 2018/9/13.
//
#include "GB28181_sender.h"
GB28181_sender::GB28181_sender(UserArguments *arg) : args(arg) {}
int GB28181_sender::initSender() {
switch (args->outType) {
case 0: // udp
LOGE("ip:%s, port:%d", args->ip_addr, args->port);
break;
case 1: // tcp
LOGE("ip:%s, port:%d", args->ip_addr, args->port);
break;
case 2: // file
//打开ps文件
LOGE("media path: %s", args->media_path);
fout.open(args->media_path, ios::binary);
break;
default:
break;
}
isRuning = RUNING;
pthread_t thread;
pthread_create(&thread, NULL, GB28181_sender::processSend, this);
LOGI("发送器初始化完成")
return 0;
}
int GB28181_sender::addPkt(uint8_t *pkt) {
pkt_queue.push(pkt);
return 0;
}
void *GB28181_sender::processSend(void *obj) {
GB28181_sender * gb28181Sender = (GB28181_sender *) obj;
while (gb28181Sender->isRuning) {
uint8_t *pkt_buf = *gb28181Sender->pkt_queue.wait_and_pop().get();
uint16_t len = bytes2short(pkt_buf);
LOGE("get pkt len: %d", len);
switch (gb28181Sender->args->outType) {
case 0: // udp
break;
case 1: // tcp
break;
case 2: // file
gb28181Sender->fout.write((const char *) (pkt_buf + 2), len);
break;
default:
break;
}
delete(pkt_buf);
}
LOGI("发送结束");
gb28181Sender->closeSender();
return nullptr;
}
int GB28181_sender::sendCloseSignal() {
isRuning = STOPED;
return 0;
}
int GB28181_sender::closeSender() {
if (stoped) {
return 0;
} else {
stoped = 1;
}
switch (args->outType) {
case 0: // udp
break;
case 1: // tcp
break;
case 2: // file
fout.close();
break;
default:
break;
}
return 0;
}
//
// Created by autulin on 2018/9/13.
//
#ifndef GB28181ANDROID_GB28181_SENDER_H
#define GB28181ANDROID_GB28181_SENDER_H
#include <fstream>
#include "base_include.h"
#include "user_arguments.h"
#define RUNING 1
#define STOPED 0
class GB28181_sender {
public:
GB28181_sender(UserArguments *arg);
static void* processSend(void *obj);
int initSender();
int addPkt(uint8_t *pkt);
int sendCloseSignal();
int closeSender();
private:
UserArguments * args;
ofstream fout;
threadsafe_queue<uint8_t *> pkt_queue;
int isRuning;
volatile int stoped;
};
#endif //GB28181ANDROID_GB28181_SENDER_H
......@@ -57,4 +57,24 @@ static uint64_t bytes2long(uint8_t b[]) {
return res;
}
static uint16_t bytes2short(uint8_t b[]) {
uint16_t temp = 0;
uint16_t res = 0;
for (int i=0;i<2;i++) {
res <<= 8;
temp = b[i];
temp = (uint16_t) (temp & 0xff);
res |= temp;
}
return res;
}
static uint8_t * short2Bytes(uint16_t i) {
uint16_t temp = i;
uint8_t * bytes = (uint8_t *) malloc(2);
bytes[1] = (uint8_t) (temp & 0xff);
temp >>= 8;
bytes[0] = (uint8_t) (temp & 0xff);
return bytes;
}
#endif //BASE_INCLUDE_H
......@@ -17,9 +17,6 @@ GB28181Muxer::GB28181Muxer(UserArguments *arg) : arguments(arg) {
int GB28181Muxer::initMuxer() {
LOGI("视频编码器初始化开始");
if (arguments->outType < 2)
LOGE("ip:%s, port:%d", arguments->ip_addr, arguments->port);
av_register_all();
pFormatCtx = avformat_alloc_context();
......@@ -98,7 +95,8 @@ int GB28181Muxer::initMuxer() {
return -1;
}
initOutput();
gb28181Sender = new GB28181_sender(arguments);
gb28181Sender->initSender();
pFrame = av_frame_alloc();
picture_size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
......@@ -178,7 +176,8 @@ void *GB28181Muxer::startMux(void *obj) {
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,
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++;
......@@ -321,9 +320,10 @@ GB28181Muxer::custom_filter(const GB28181Muxer *gb28181Muxer, const uint8_t *pic
*/
int GB28181Muxer::endMux() {
LOGE("endMux");
closeOutput();
gb28181Sender->sendCloseSignal();
LOGE("aduio queue left num: %d, video queue left num: %d", audio_queue.size(), video_queue.size());
LOGE("aduio queue left num: %d, video queue left num: %d", audio_queue.size(),
video_queue.size());
audio_queue.clear();
video_queue.clear();
......@@ -336,6 +336,7 @@ int GB28181Muxer::endMux() {
// avio_close(pFormatCtx->pb);
avformat_free_context(pFormatCtx);
LOGI("视频编码结束")
// gb28181Sender->closeSender(); //再发一次防止之前没关掉
return 1;
}
......@@ -352,6 +353,7 @@ int GB28181Muxer::mux(GB28181Muxer *gb28181Muxer) {
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];
int nSizePos = 0;
......@@ -364,10 +366,10 @@ int GB28181Muxer::mux(GB28181Muxer *gb28181Muxer) {
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);
delete (picture_buf);
gb28181Muxer->pFrame->pts = (v_time - gb28181Muxer->startTime) * 90;
LOGE("v_time: %lld, get a pts:%lld (aduio queue left num: %d, video queue left num: %d)"
, v_time, gb28181Muxer->pFrame->pts, audio_queue.size(), video_queue.size());
LOGE("v_time: %lld, get a pts:%lld (aduio queue left num: %d, video queue left num: %d)",
v_time, gb28181Muxer->pFrame->pts, audio_queue.size(), video_queue.size());
int got_picture;
int ret = avcodec_encode_video2(gb28181Muxer->pCodecCtx, gb28181Muxer->nextPkt,
......@@ -406,10 +408,21 @@ int GB28181Muxer::mux(GB28181Muxer *gb28181Muxer) {
// video psm
gb28181_make_pes_header(szTempPacketHead + nSizePos, 0xE0, nSize, lastPts, lastPts);
nSizePos += PES_HDR_LEN;
gb28181Muxer->fout.write(szTempPacketHead, nSizePos);
gb28181Muxer->fout.write(reinterpret_cast<const char *>(gb28181Muxer->nowPkt->data), nSize);
// gb28181Muxer->fout.write(szTempPacketHead, nSizePos);
// gb28181Muxer->fout.write(reinterpret_cast<const char *>(gb28181Muxer->nowPkt->data), nSize);
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);
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);
pktPos += nSizePos;
memcpy(pkt_full + pktPos, gb28181Muxer->nowPkt->data, nSize);
pktPos+= nSize;
// LOGE("orgin frame:%ld", h264_encoder->nowPkt->pts);
gb28181Muxer->nowPkt->stream_index = gb28181Muxer->video_st->index;
AVPacket *t = gb28181Muxer->nowPkt;
......@@ -421,48 +434,21 @@ int GB28181Muxer::mux(GB28181Muxer *gb28181Muxer) {
while (audioCnt > 0) {
uint8_t *audioFrame = *gb28181Muxer->audio_queue.wait_and_pop().get();
int64_t audioPts = gb28181Muxer->audioFrameCnt * 3600; // 音频默认25帧,90000/25=3600
int aFrameLen = gb28181Muxer->arguments->a_frame_len / 2;
gb28181_make_pes_header(szTempPacketHead + nSizePos, 0xC0, aFrameLen, audioPts,
audioPts);
fout.write(szTempPacketHead + nSizePos, PES_HDR_LEN);
memcpy(pkt_full + pktPos, szTempPacketHead + nSizePos, PES_HDR_LEN);
pktPos+=PES_HDR_LEN;
// fout.write(szTempPacketHead + nSizePos, PES_HDR_LEN);
nSizePos += PES_HDR_LEN;
fout.write(reinterpret_cast<char *>(audioFrame), aFrameLen);
memcpy(pkt_full + pktPos, audioFrame, aFrameLen);
pktPos+= aFrameLen;
// fout.write(reinterpret_cast<char *>(audioFrame), aFrameLen);
gb28181Muxer->audioFrameCnt++;
audioCnt--;
delete (audioFrame);
}
gb28181Sender->addPkt(pkt_full);
}
LOGE("mux over!");
return 0;
}
void GB28181Muxer::initOutput() {
switch (arguments->outType) {
case 0: // udp
break;
case 1: // tcp
break;
case 2: // file
//打开ps文件
LOGE("media path: %s", arguments->media_path);
fout.open(arguments->media_path, ios::binary);
break;
default:
break;
}
}
void GB28181Muxer::closeOutput() {
switch (arguments->outType) {
case 0: // udp
break;
case 1: // tcp
break;
case 2: // file
fout.close();
break;
default:
break;
}
}
\ No newline at end of file
......@@ -8,6 +8,7 @@
#include "base_include.h"
#include "user_arguments.h"
#include "GB28181_sender.h"
#include <sys/time.h>
......@@ -40,6 +41,7 @@ private:
private:
UserArguments *arguments;
GB28181_sender *gb28181Sender;
int is_end = START_STATE;
int is_release = RELEASE_FALSE;
threadsafe_queue<uint8_t *> video_queue;
......@@ -60,12 +62,8 @@ private:
int videoFrameCnt = 0;
int64_t startTime = 0;
ofstream fout;
int mux(GB28181Muxer *gb28181Muxer);
void initOutput();
void closeOutput();
};
#endif //GB281818_MUXER_H
......@@ -40,7 +40,8 @@ Java_com_autulin_gb28181library_JNIBridge_initMuxer(JNIEnv *env, jclass type, js
jclass global_class = (jclass) env->NewGlobalRef(type);
UserArguments *arguments = (UserArguments *) malloc(sizeof(UserArguments));
arguments->ip_addr = ip;
arguments->ip_addr = (char *) malloc(strlen(ip) + 1);
strcpy(arguments->ip_addr, ip);
arguments->port = port;
arguments->outType = outType;
arguments->media_base_path = mediaBasePath;
......
......@@ -6,7 +6,7 @@
#include "jni.h"
class JNIHandler;
typedef struct UserArguments {
const char *ip_addr;
char *ip_addr;
int port;
int outType;
const char *media_base_path; //文件储存地址
......
......@@ -69,6 +69,7 @@ public class DemoActivity extends AppCompatActivity implements
// MediaRecorderBase.SMALL_VIDEO_HEIGHT = mediaRecorderConfig.getSmallVideoHeight();
// MediaRecorderBase.SMALL_VIDEO_WIDTH = mediaRecorderConfig.getSmallVideoWidth();
// MediaRecorderBase.mVideoBitrate = mediaRecorderConfig.getVideoBitrate();
Log.i("debug", "SMALL_VIDEO_HEIGHT: " + MediaRecorderBase.SMALL_VIDEO_HEIGHT + ", SMALL_VIDEO_WIDTH:" + MediaRecorderBase.SMALL_VIDEO_WIDTH );
}
private void initView() {
......@@ -89,6 +90,7 @@ public class DemoActivity extends AppCompatActivity implements
// String fileName = String.valueOf(System.currentTimeMillis());
String fileName = "tttttt";
mediaOutput = mMediaRecorder.setFileOutPut(fileName);
// mediaOutput = mMediaRecorder.setUdpOutPut("10.112.181.160", 8888);
mMediaRecorder.setSurfaceHolder(mSurfaceView.getHolder());
mMediaRecorder.prepare();
......
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DemoActivity">
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
......@@ -24,8 +22,7 @@
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:text="开始录制"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:text="开始录制"/>
</RelativeLayout>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论