Android中通过Wi-Fi或LAN通过TCP和RTSP的流式客户端
我正在努力为DVR摄像机开发流媒体客户端,我尝试通过RTSP协议使用VLC Media player,我得到了解决方案(使用Wi-Fi标准型号,如Netgear等),但相同的代码不支持其他Wi-Fi调制解调器,现在我正与FFMPEG框架合作,使用JNI API在android中实现流媒体客户端。没有任何正确的想法来实现JNIAPI 网络摄像头与应用程序一起工作 代码如下:Android中通过Wi-Fi或LAN通过TCP和RTSP的流式客户端,android,tcp,ffmpeg,streaming,Android,Tcp,Ffmpeg,Streaming,我正在努力为DVR摄像机开发流媒体客户端,我尝试通过RTSP协议使用VLC Media player,我得到了解决方案(使用Wi-Fi标准型号,如Netgear等),但相同的代码不支持其他Wi-Fi调制解调器,现在我正与FFMPEG框架合作,使用JNI API在android中实现流媒体客户端。没有任何正确的想法来实现JNIAPI 网络摄像头与应用程序一起工作 代码如下: /*****************************************************/ /* fun
/*****************************************************/
/* functional call */
/*****************************************************/
jboolean Java_FFmpeg_allocateBuffer( JNIEnv* env, jobject thiz )
{
// Allocate an AVFrame structure
pFrameRGB=avcodec_alloc_frame();
if(pFrameRGB==NULL)
return 0;
sprintf(debugMsg, "%d %d", screenWidth, screenHeight);
INFO(debugMsg);
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(dstFmt, screenWidth, screenHeight);
/*
numBytes=avpicture_get_size(dstFmt, pCodecCtx->width,
pCodecCtx->height);
*/
buffer=(uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
avpicture_fill((AVPicture *)pFrameRGB, buffer, dstFmt, screenWidth, screenHeight);
return 1;
}
/* for each decoded frame */
jbyteArray Java_FFmpeg_getNextDecodedFrame( JNIEnv* env, jobject thiz )
{
av_free_packet(&packet);
while(av_read_frame(pFormatCtx, &packet)>=0) {
if(packet.stream_index==videoStream) {
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if(frameFinished) {
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, screenWidth, screenHeight, dstFmt, SWS_BICUBIC, NULL, NULL, NULL);
/*
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, dstFmt, SWS_BICUBIC, NULL, NULL, NULL);
*/
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize,
0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
++frameCount;
/* uint8_t == unsigned 8 bits == jboolean */
jbyteArray nativePixels = (*env)->NewByteArray(env, numBytes);
(*env)->SetByteArrayRegion(env, nativePixels, 0, numBytes, buffer);
return nativePixels;
}
}
av_free_packet(&packet);
}
return NULL;
}
/*****************************************************/
/* / functional call */
/*****************************************************/
jstring
Java_FFmpeg_play( JNIEnv* env, jobject thiz, jstring jfilePath )
{
INFO("--- Play");
char* filePath = (char *)(*env)->GetStringUTFChars(env, jfilePath, NULL);
RE(filePath);
/*****************************************************/
AVFormatContext *pFormatCtx;
int i, videoStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame;
AVPacket packet;
int frameFinished;
float aspect_ratio;
struct SwsContext *img_convert_ctx;
INFO(filePath);
/* FFmpeg */
av_register_all();
if(av_open_input_file(&pFormatCtx, filePath, NULL, 0, NULL)!=0)
RE("failed av_open_input_file ");
if(av_find_stream_info(pFormatCtx)<0)
RE("failed av_find_stream_info");
videoStream=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
videoStream=i;
break;
}
if(videoStream==-1)
RE("failed videostream == -1");
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL) {
RE("Unsupported codec!");
}
if(avcodec_open(pCodecCtx, pCodec)<0)
RE("failed codec_open");
pFrame=avcodec_alloc_frame();
/* /FFmpeg */
INFO("codec name:");
INFO(pCodec->name);
INFO("Getting into stream decode:");
/* video stream */
i=0;
while(av_read_frame(pFormatCtx, &packet)>=0) {
if(packet.stream_index==videoStream) {
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if(frameFinished) {
++i;
INFO("frame finished");
AVPicture pict;
/*
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize,
0, pCodecCtx->height, pict.data, pict.linesize);
*/
}
}
av_free_packet(&packet);
}
/* /video stream */
av_free(pFrame);
avcodec_close(pCodecCtx);
av_close_input_file(pFormatCtx);
RE("end of main");
}
/*****************************************************/
/*函数调用*/
/*****************************************************/
jboolean Java_FFmpeg_allocateBuffer(JNIEnv*env,jobject thiz)
{
//分配一个AVFrame结构
pFrameRGB=avcodec_alloc_frame();
if(pFrameRGB==NULL)
返回0;
sprintf(debugMsg,“%d%d”,屏幕宽度,屏幕高度);
信息(debugMsg);
//确定所需的缓冲区大小并分配缓冲区
numBytes=平均图片大小(dstFmt、屏幕宽度、屏幕高度);
/*
numBytes=avpicture\u get\u size(dstFmt、pCodecCtx->width,
pCodecCtx->高度);
*/
缓冲区=(uint8_t*)av_malloc(numBytes*sizeof(uint8_t));
//将缓冲区的适当部分指定给pFrameRGB中的图像平面
//请注意,pFrameRGB是一个AVFrame,但AVFrame是一个超集
//AVPicture的应用
avpicture_填充((avpicture*)pFrameRGB、缓冲区、dstFmt、屏幕宽度、屏幕高度);
返回1;
}
/*对于每个解码帧*/
jbyteArray Java_FFmpeg_GetNextDecodeFrame(JNIEnv*env,jobject thiz)
{
av_免费_数据包(&数据包);
而(av_读取_帧(pFormatCtx和数据包)>=0){
if(数据包流\索引==视频流){
avcodec_decode_video2(pCodecCtx、pFrame、frameFinished和packet);
如果(帧完成){
img_convert_ctx=sws_getContext(pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,screenWidth,screenHeight,dstFmt,sws_双三次,NULL,NULL,NULL);
/*
img_convert_ctx=sws_getContext(pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,pCodecCtx->width,pCodecCtx->height,dstFmt,sws_BICUBIC,NULL,NULL);
*/
sws_比例(img_转换ctx,(常数uint8_t*常数*)pFrame->数据,pFrame->线条尺寸,
0,pCodecCtx->height,pFrameRGB->data,pFrameRGB->linesize);
++帧数;
/*uint8_t==无符号8位==jboolean*/
jbyterarray nativePixels=(*env)->NewByteArray(env,numBytes);
(*env)->SetByteArrayRegion(env,nativePixels,0,numBytes,buffer);
返回本地像素;
}
}
av_免费_数据包(&数据包);
}
返回NULL;
}
/*****************************************************/
/*/功能调用*/
/*****************************************************/
jstring
Java_FFmpeg_play(JNIEnv*env、jobject thiz、jstring jfilePath)
{
信息(“播放”);
char*filePath=(char*)(*env)->GetStringUTFChars(env,jfilePath,NULL);
RE(文件路径);
/*****************************************************/
AVFormatContext*pFormatCtx;
inti,视频流;
AVCodecContext*pCodecCtx;
AVCodec*pCodec;
AVFrame*pFrame;
数据包;
int框架完成;
浮动纵横比;
结构SwsContext*img\u convert\u ctx;
信息(文件路径);
/*FFmpeg*/
av_寄存器_all();
如果(av_打开_输入_文件(&pFormatCtx,filePath,NULL,0,NULL)!=0)
RE(“未能打开AVU输入文件”);
如果(av\u查找\u流\u信息(pFormatCtx)流[i]->编解码器->编解码器\u类型==AVMEDIA\u类型\u视频){
视频流=i;
打破
}
如果(视频流==-1)
RE(“失败的视频流==-1”);
pCodecCtx=pFormatCtx->streams[videoStream]->编解码器;
pCodec=avcodec\u find\u解码器(pCodecCtx->codec\u id);
if(pCodec==NULL){
RE(“不支持的编解码器!”);
}
if(avcodec_open(pCodecCtx,pCodec)名称);
信息(“进入流解码:”;
/*视频流*/
i=0;
而(av_读取_帧(pFormatCtx和数据包)>=0){
if(数据包流\索引==视频流){
avcodec_decode_video2(pCodecCtx、pFrame、frameFinished和packet);
如果(框架完成){
++一,;
信息(“框架完成”);
AVPICT;
/*
img\u convert\u ctx=sws\u getContext(pCodecCtx->width,pCodecCtx->height,
PCODECTX->pix_fmt,PCODECTX->宽度,PCODECTX->高度,
PIX_FMT_YUV420P,SWS_双三次,NULL,NULL,NULL);
sws_比例(img_转换ctx,(常数uint8_t*常数*)pFrame->数据,pFrame->线条尺寸,
0,pCodecCtx->高度,图像数据,图像线条尺寸);
*/
}
}
av_免费_数据包(&数据包);
}
/*/视频流*/
无AVU(pFrame);
avcodec_关闭(PCODECTX);
av_关闭_输入_文件(pFormatCtx);
RE(“主管道末端”);
}
我无法从网络摄像机中获取帧
并给出在Android中实现DVR摄像机直播客户端的一些想法,这需要大量代码。你能试着做一个决定吗?请告诉我们,代码中的问题在哪里。请让它更容易帮助你。你好,喇叭代码修改