Android中通过Wi-Fi或LAN通过TCP和RTSP的流式客户端

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

我正在努力为DVR摄像机开发流媒体客户端,我尝试通过RTSP协议使用VLC Media player,我得到了解决方案(使用Wi-Fi标准型号,如Netgear等),但相同的代码不支持其他Wi-Fi调制解调器,现在我正与FFMPEG框架合作,使用JNI API在android中实现流媒体客户端。没有任何正确的想法来实现JNIAPI

网络摄像头与应用程序一起工作

代码如下:

/*****************************************************/
/* 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摄像机直播客户端的一些想法,这需要大量代码。你能试着做一个决定吗?请告诉我们,代码中的问题在哪里。请让它更容易帮助你。你好,喇叭代码修改