ffmpeg rtsp

来源:互联网 发布:网络政治参与图片 编辑:程序博客网 时间:2024/06/06 07:00
#include <libavcodec/avcodec.h>#include <libavdevice/avdevice.h>#include <libavformat/avformat.h>#include <libavfilter/avfilter.h>#include <libavutil/avutil.h>#include <libswscale/swscale.h>#include "x264_config.h"#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <math.h>#include <time.h>#include <sys/time.h>#include <jni.h>#include <android/log.h> #define LOG_TAG  "librtsp0"#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))static AVFormatContext *i_fmt_ctx;static AVStream *i_video_stream;static AVFormatContext *o_fmt_ctx;static AVStream *o_video_stream;signed char bStop = 0;signed char rtsp2mp4(const char *psdp, const char *pfile){      unsigned i;    int ret;    const char *rtspUrl = psdp;    const char *filename = pfile;    //注册FFmpeg所有编解码器      avcodec_register_all();    av_register_all();    //rtsp需网络支持    avformat_network_init();    /* should set to NULL so that avformat_open_input() allocate a new one */    i_fmt_ctx = NULL;    //根据输入,初始化输入视频码流的AVFormatContext    if(avformat_open_input(&i_fmt_ctx, rtspUrl, NULL, NULL)!=0) {        LOGI("             could not open input file              ");        return -1;    }    //从输入AVFormatContext查找stream     if(avformat_find_stream_info(i_fmt_ctx, NULL)<0) {        LOGI("             could not find stream info              ");        return -1;    }    LOGI("              start                ");    //av_dump_format(i_fmt_ctx, 0, rtspUrl, 0);    /* find first video stream */    for (i=0; i<i_fmt_ctx->nb_streams; i++) {        if (i_fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {            i_video_stream = i_fmt_ctx->streams[i]; //找到具体的video stream, i 即为stream index            break;        }    }    if (i_video_stream == NULL) {        LOGI("             didn't find any video stream              ");        return -1;    }    LOGI("              start 1               ");    //根据输出文嘉类型创建相应的输出AVFormatContext    avformat_alloc_output_context2(&o_fmt_ctx, NULL, NULL, filename);    /*    * since all input files are supposed to be identical (framerate, dimension, color format, ...)    * we can safely set output codec values from first input file    */    //根据输出的AVFormatContext创建相应的输出stream    o_video_stream = avformat_new_stream(o_fmt_ctx, NULL);    //拷贝输入视频码流的AVCodecContex的数值t到输出视频的AVCodecContext    ret = avcodec_copy_context(out_stream->codec, in_stream->codec);      if (ret < 0) {         LOGI("Failed to copy context from input to output stream codec context\n");         return -1;      }     /*       LOGI("              start 2               ");    {        AVCodecContext *c;        c = o_video_stream->codec;        c->bit_rate = 400000;        c->codec_id      = i_video_stream->codec->codec_id;        c->codec_type    = i_video_stream->codec->codec_type;        c->time_base.num = i_video_stream->time_base.num;        c->time_base.den = i_video_stream->time_base.den;        c->width         = i_video_stream->codec->width;        c->height        = i_video_stream->codec->height;        c->pix_fmt       = i_video_stream->codec->pix_fmt;        c->flags         = i_video_stream->codec->flags;        c->flags        |= CODEC_FLAG_GLOBAL_HEADER;        c->me_range      = i_video_stream->codec->me_range;        c->max_qdiff     = i_video_stream->codec->max_qdiff;        c->qmin          = i_video_stream->codec->qmin; //量化参数min        c->qmax          = i_video_stream->codec->qmax; //量化参数max        c->qcompress     = i_video_stream->codec->qcompress;        LOGI("     c->codec_id = %d, num = %d, den = %d   ", c->codec_id, c->time_base.num, c->time_base.den);    }    */    avio_open(&o_fmt_ctx->pb, filename, AVIO_FLAG_WRITE);    ret = avformat_write_header(o_fmt_ctx, NULL);    LOGI("    c->width = %d, c->height = %d, c->pix_fmt= %d  ", i_video_stream->codec->width,    i_video_stream->codec->height,      i_video_stream->codec->pix_fmt);    int last_pts = 0;    int last_dts = 0;    int64_t pts, dts;    int num_rec = 0;    while (bStop==0)    {        AVPacket i_pkt;        av_init_packet(&i_pkt);        i_pkt.size = 0;        i_pkt.data = NULL;        if (av_read_frame(i_fmt_ctx, &i_pkt) <0 ) //读取帧填入AVPacket            break;        /*        * pts and dts should increase monotonically        * pts should be >= dts        */        i_pkt.flags |= AV_PKT_FLAG_KEY;        pts          = i_pkt.pts;        i_pkt.pts   += last_pts;        dts = i_pkt.dts;        i_pkt.dts += last_dts;        i_pkt.stream_index = 0;        static int num = 1;        num++;        if(++num_rec>40){           num_rec = 0;           LOGI("             num = %d            ", num);        }        av_interleaved_write_frame(o_fmt_ctx, &i_pkt);        //av_free_packet(&i_pkt);        usleep(25000);    }    last_dts += dts;    last_pts += pts;    avformat_close_input(&i_fmt_ctx); //关闭输入端的AVFormatContext,对应avformat_open_input函数    av_write_trailer(o_fmt_ctx);    avcodec_close(o_fmt_ctx->streams[0]->codec);    av_freep(&o_fmt_ctx->streams[0]->codec);    av_freep(&o_fmt_ctx->streams[0]);    avio_close(o_fmt_ctx->pb); //关闭输出端的AVFormatContext probe功能,对应avio_open函数    av_free(o_fmt_ctx);    LOGI("              End              ");    return 0;}JNIEXPORT void JNICALL Java_com_example_myrtsp0_MainActivity_RtspMp4Start (JNIEnv *env, jclass clz, jstring sdp, jstring mp4) {    const char* sdp_title = (*env)->GetStringUTFChars(env, sdp, NULL);    const char* mp4_title = (*env)->GetStringUTFChars(env, mp4, NULL);    bStop = 0;  signed char ret = rtsp2mp4(sdp_title, mp4_title);  LOGI("              RtspMp4 = %d              ", ret);    (*env)->ReleaseStringUTFChars(env, sdp, sdp_title);    (*env)->ReleaseStringUTFChars(env, mp4, mp4_title); }//视频录制结束调用JNIEXPORT void Java_com_example_myrtsp0_MainActivity_RtspMp4End(JNIEnv *env, jclass clz){    bStop = 1;    LOGI("              RtspMp4End              ");}
0 0
原创粉丝点击