FFmpeg使用RTSP流直接保存成mp4碰到的问题

zhuzhen_17 2015-05-07 04:33:46
功能是要在android手机上播放rtsp流的同时把流信息保存成mp4文件,播放的功能已经做好了
由于一直做的Java和android,所有C能力几乎为0,做播放的时候已经费了很大的力气,现在要做保存MP4又是一头雾水
下面的代码是在网上找的,然后有些问题,在执行到av_interleaved_write_frame的时候,第1次没问题,第2次也没问题,第3次就会出现返回值为-22的问题。
看代码发现last_dts += dts;last_pts += pts;这两行好像没有意义,然后我尝试把这两行加入到while循环里面去,这样的话-22的问题没有了,生存的MP4文件但是无法播放。
求大神们看看,如果大神们有demo的话也请发送至zhuzhen_17@163.com,万分感谢!


#include <jni.h>
#include <string.h>
#include <stdio.h>

#include "FFmpeg.h"
#include "../include/libavcodec/avcodec.h"
#include "../include/libavformat/avformat.h"
#include "../include/libswscale/swscale.h"

//#define LOG_TAG "FFMPEGSample"
//#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
//#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

#define IS_DEBUG 1
#define LOG_TAG __FILE__
#define LOGI(...) if(IS_DEBUG){__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__);}

int pPlayFlag;

JNIEXPORT jint JNICALL Java_com_crodigy_intelligent_ffmpeg_FFmpegUtils_TranscribeTest1(JNIEnv * env, jobject obj, jstring rtspUrl, jstring outFileUrl) {

pPlayFlag = 0;
AVFormatContext *i_fmt_ctx;
AVStream *i_video_stream;

AVFormatContext *o_fmt_ctx;
AVStream *o_video_stream;
AVCodec *codec = NULL;
avcodec_register_all();
av_register_all();
avformat_network_init();
int ptsInc = 0;

/* should set to NULL so that avformat_open_input() allocate a new one */
i_fmt_ctx = NULL;
const char* m_rtspUrl = (*env)->GetStringUTFChars(env, rtspUrl, NULL);
const char* m_outFileUrl = (*env)->GetStringUTFChars(env, outFileUrl, NULL);
LOGI("rtsp--->%s", m_rtspUrl);
if (avformat_open_input(&i_fmt_ctx, m_rtspUrl, NULL, NULL) != 0) {
LOGI("could not open input file");
return -1;
}

if (avformat_find_stream_info(i_fmt_ctx, NULL) < 0) {
LOGI("could not find stream info");
return -1;
}

/* find first video stream */
unsigned i;
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];
break;
}
}
if (i_video_stream == NULL) {
LOGI("didn't find any video stream");
return -1;
}

// codec = avcodec_find_decoder(i_video_stream->codec->codec_id);
// if (codec == NULL) {
// LOGI("decoder not found");
// return -1;
// }
//
// if (avcodec_open2(i_video_stream->codec, codec, NULL) < 0) {
// LOGI("Codec not found");
// return -1;
// }

avformat_alloc_output_context2(&o_fmt_ctx, NULL, NULL, m_outFileUrl);
if (!o_fmt_ctx) {
LOGI("Could not deduce output format from file extension: using MPEG.1");
avformat_alloc_output_context2(&o_fmt_ctx, NULL, "mpeg", m_outFileUrl);
}
if (!o_fmt_ctx) {
LOGI("Could not deduce output format from file extension: using MPEG.2");
return -1;
}

/*
* since all input files are supposed to be identical (framerate, dimension, color format, ...)
* we can safely set output codec values from first input file
*/
o_video_stream = avformat_new_stream(o_fmt_ctx, NULL);
{
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;
c->qmax = i_video_stream->codec->qmax;

c->qcompress = i_video_stream->codec->qcompress;
LOGI("codec_id %d codec_type %d", i_video_stream->codec->codec_id, i_video_stream->codec->codec_type);
LOGI("time_base.num = %d time_base.den = %d\n", c->time_base.num, c->time_base.den);
LOGI("%d %d %d", c->width, c->height, c->pix_fmt);
}

int avio_open_success = avio_open(&o_fmt_ctx->pb, m_outFileUrl, AVIO_FLAG_WRITE);
if (avio_open_success != 0) {
LOGI("avio_open is error!");
return -1;
}
int write_success = avformat_write_header(o_fmt_ctx, NULL);
if (write_success != 0) {
LOGI("avformat_write_header is error!");
return -1;
}

int last_pts = 0;
int last_dts = 0;

int64_t pts, dts;
while (1) {

static int num = 1;
LOGI("frame %d\n", num++);
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 || pPlayFlag == -1)
break;

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;

int ret = av_interleaved_write_frame(o_fmt_ctx, &i_pkt);
if (ret < 0) {
LOGI("av_interleaved_write_frame is error! ret-->%d", ret);
break;
// return -1;
}
}
last_dts += dts;
last_pts += pts;
avformat_close_input(&i_fmt_ctx);
LOGI("avformat_close_input");
write_success = av_write_trailer(o_fmt_ctx);
if (write_success != 0) {
LOGI("av_write_trailer is error!");
}
LOGI("av_write_trailer");
avcodec_close(o_fmt_ctx->streams[0]->codec);
LOGI("avcodec_close");
av_freep(&o_fmt_ctx->streams[0]->codec);
LOGI("av_freep");
av_freep(&o_fmt_ctx->streams[0]);
LOGI("av_freep");
avio_close(o_fmt_ctx->pb);
LOGI("avio_close");
av_free(o_fmt_ctx);
LOGI("av_free");
return 0;
}

JNIEXPORT jint JNICALL Java_com_crodigy_intelligent_ffmpeg_FFmpegUtils_DecodeRelease(JNIEnv * env, jobject obj) {
LOGI("Java_com_crodigy_intelligent_ffmpeg_FFmpegUtils_DecodeRelease");
pPlayFlag = -1;
return 1;
}
...全文
1372 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
此后三年 2015-05-08
  • 打赏
  • 举报
回复
推荐一个群给你 256061378 , ffmpeg我也正在学习中, 到这个群里问问, 好多高手。

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧