ffmpeg問題の要約と解決策
14546 ワード
1:rtp/rtsp転送であれば、ffmpegは30 sおきに(どこで設定しますか?)ipcがGET_をサポートしている場合、keepaliveパッケージを送信します.PARAMETERコマンドは、そのコマンドを発行してipcがまだ生きていることを確認するためにipcに返信します.一部のipc(IPCamera)はGET_をサポートしていませんPARAMETERのrtspコマンド.OPTIONS*を介してkeepaliveになりますが、元のコードが切断され、次のように変更されます.まずこのように処理して、時間があってから元のコードがどうしてこのように処理しないのかを研究します.
2:rtp/rtsp/tcp転送でstimout(socket timeout)が設定されていない場合、server断線後av_read_フレームが詰まる
ffmpeg 2なら.0.1バージョンなら、一言追加すればOKです.しかし旧バージョンffmpeg 1.2.*stimeoutというフィールドが設定されていないので、自分で追加するしかありません.ffmpeg/libavformat/rtsp.h struct RTSPState stimeoutフィールドを追加
ffmpeg/libavformat/rtsp.c ff_rtsp_options stimeoutフィールドを追加
ffmpeg/libavformat/rtsp.c ff_rtsp_connect関数の変更部分のコードは以下の通りです.
オリジナルのアドレス:http://blog.chinaunix.net/uid-27091949-id-4186640.html
1:rtp/rtsp転送であれば、ffmpegは30 sおきに(どこで設定しますか?)ipcがGET_をサポートしている場合、keepaliveパッケージを送信します.PARAMETERコマンドは、そのコマンドを発行してipcがまだ生きていることを確認するためにipcに返信します.一部のipc(IPCamera)はGET_をサポートしていませんPARAMETERのrtspコマンド.OPTIONS*を介してkeepaliveになりますが、元のコードが切断され、次のように変更されます.まずこのように処理して、時間があってから元のコードがどうしてこのように処理しないのかを研究します.
折りたたむか開くかクリック
//ffmpeg/libavformat/rtspdec.c rtsp_read_packet()
if (!(rt->rtsp_flags & RTSP_FLAG_LISTEN)) {
/* send dummy request to keep TCP connection alive */
if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2 ||
rt->auth_state.stale) {
if (rt->server_type == RTSP_SERVER_WMS ||
(rt->server_type != RTSP_SERVER_REAL &&
rt->get_parameter_supported)) {
ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
} else {
// ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL);//コード ff_rtsp_send_cmd_async(s, "OPTIONS", rt->control_uri, NULL);//修正後のコードは、ipcがGETをサポートしなくてもPARAMETERの命令はkeepaliveできます }
/* The stale flag should be reset when creating the auth response in
* ff_rtsp_send_cmd_async, but reset it here just in case we never
* called the auth code (if we didn't have any credentials set). */
rt->auth_state.stale = 0;
}
}
2:rtp/rtsp/tcp転送でstimout(socket timeout)が設定されていない場合、server断線後av_read_フレームが詰まる
折りたたむか開くかクリック
AVFormatContext *pFormatCtx = NULL;
AVPacket packet;
AVDictionary *optionsDict = NULL;
char *streamurl1 = "rtsp://test:[email protected]:554/test.stream";
// Register all formats and codecs
av_register_all();
avformat_network_init();
pFormatCtx = avformat_alloc_context();
av_dict_set(&optionsDict, "rtsp_transport", "tcp", 0);//tcp伝送採用
av_dict_set(&optionsDict, "stimeout", "2000000", 0);//stimeoutが設定されていない場合はipcケーブルを抜いてav_read_frameはブロックされます(時間単位は微妙です)
// Open video file
if(avformat_open_input(&pFormatCtx, streamurl, NULL, &optionsDict)!=0){
printf("linesize = %d", __LINE__);
return -1; // Couldn't open file
}
// Retrieve stream information
if(avformat_find_stream_info(pFormatCtx, NULL)<0){
printf("linesize = %d", __LINE__);
return -1; // Couldn't find stream information
}
// Find the first video stream
int videoStream=-1;
for(i=0; inb_streams; i++){
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
videoStream=i;
break;
}
}
if(videoStream==-1){
printf("linesize = %d", __LINE__);
return -1; // Didn't find a video stream
}
// Read frames and save first five frames to disk
while(av_read_frame(pFormatCtx, &packet)>=0) {
av_free_packet(&packet);
}
ffmpeg 2なら.0.1バージョンなら、一言追加すればOKです.しかし旧バージョンffmpeg 1.2.*stimeoutというフィールドが設定されていないので、自分で追加するしかありません.ffmpeg/libavformat/rtsp.h struct RTSPState stimeoutフィールドを追加
折りたたむか開くかクリック
typedef struct RTSPState {
/**
* timeout of socket i/o operations.(this version do not have this segment. added by yqing, refer to ffmpeg-2.0.1)
*/
int stimeout;
} RTSPState;
ffmpeg/libavformat/rtsp.c ff_rtsp_options stimeoutフィールドを追加
折りたたむか開くかクリック
const AVOption ff_rtsp_options[] = {
{ "stimeout", "timeout (in micro seconds) of socket i/o operations.", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX,DEC},//この行のコードを追加
RTSP_REORDERING_OPTS(),
{ NULL },
};
ffmpeg/libavformat/rtsp.c ff_rtsp_connect関数の変更部分のコードは以下の通りです.
折りたたむか開くかクリック
//ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);//コード ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, "?timeout=%d", rt->stimeout);//修正後のコード
//ffmpeg/libavformat/rtspdec.c rtsp_read_packet()
if (!(rt->rtsp_flags & RTSP_FLAG_LISTEN)) {
/* send dummy request to keep TCP connection alive */
if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2 ||
rt->auth_state.stale) {
if (rt->server_type == RTSP_SERVER_WMS ||
(rt->server_type != RTSP_SERVER_REAL &&
rt->get_parameter_supported)) {
ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
} else {
// ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL); //
ff_rtsp_send_cmd_async(s, "OPTIONS", rt->control_uri, NULL); // , ipc GET_PARAMETER keepalive
}
/* The stale flag should be reset when creating the auth response in
* ff_rtsp_send_cmd_async, but reset it here just in case we never
* called the auth code (if we didn't have any credentials set). */
rt->auth_state.stale = 0;
}
}
2:rtp/rtsp/tcp転送でstimout(socket timeout)が設定されていない場合、server断線後av_read_フレームが詰まる
AVFormatContext *pFormatCtx = NULL;
AVPacket packet;
AVDictionary *optionsDict = NULL;
char *streamurl1 = "rtsp://test:[email protected]:554/test.stream";
// Register all formats and codecs
av_register_all();
avformat_network_init();
pFormatCtx = avformat_alloc_context();
av_dict_set(&optionsDict, "rtsp_transport", "tcp", 0); // tcp
av_dict_set(&optionsDict, "stimeout", "2000000", 0); // stimeout, ipc ,av_read_frame ( )
// Open video file
if(avformat_open_input(&pFormatCtx, streamurl, NULL, &optionsDict)!=0){
printf("linesize = %d
", __LINE__);
return -1; // Couldn't open file
}
// Retrieve stream information
if(avformat_find_stream_info(pFormatCtx, NULL)<0){
printf("linesize = %d
", __LINE__);
return -1; // Couldn't find stream information
}
// Find the first video stream
int videoStream=-1;
for(i=0; inb_streams; i++){
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
videoStream=i;
break;
}
}
if(videoStream==-1){
printf("linesize = %d
", __LINE__);
return -1; // Didn't find a video stream
}
// Read frames and save first five frames to disk
while(av_read_frame(pFormatCtx, &packet)>=0) {
av_free_packet(&packet);
}
ffmpeg 2なら.0.1バージョンなら、一言追加すればOKです.しかし旧バージョンffmpeg 1.2.*stimeoutというフィールドが設定されていないので、自分で追加するしかありません.ffmpeg/libavformat/rtsp.h struct RTSPState stimeoutフィールドを追加
typedef struct RTSPState {
/**
* timeout of socket i/o operations.(this version do not have this segment. added by yqing, refer to ffmpeg-2.0.1)
*/
int stimeout;
} RTSPState;
ffmpeg/libavformat/rtsp.c ff_rtsp_options stimeoutフィールドを追加
const AVOption ff_rtsp_options[] = {
{ "stimeout", "timeout (in micro seconds) of socket i/o operations.", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC }, //
RTSP_REORDERING_OPTS(),
{ NULL },
};
ffmpeg/libavformat/rtsp.c ff_rtsp_connect関数の変更部分のコードは以下の通りです.
//ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL); //
ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, "?timeout=%d", rt->stimeout); //
オリジナルのアドレス:http://blog.chinaunix.net/uid-27091949-id-4186640.html
1:rtp/rtsp転送であれば、ffmpegは30 sおきに(どこで設定しますか?)ipcがGET_をサポートしている場合、keepaliveパッケージを送信します.PARAMETERコマンドは、そのコマンドを発行してipcがまだ生きていることを確認するためにipcに返信します.一部のipc(IPCamera)はGET_をサポートしていませんPARAMETERのrtspコマンド.OPTIONS*を介してkeepaliveになりますが、元のコードが切断され、次のように変更されます.まずこのように処理して、時間があってから元のコードがどうしてこのように処理しないのかを研究します.
折りたたむか開くかクリック
//ffmpeg/libavformat/rtspdec.c rtsp_read_packet()
if (!(rt->rtsp_flags & RTSP_FLAG_LISTEN)) {
/* send dummy request to keep TCP connection alive */
if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2 ||
rt->auth_state.stale) {
if (rt->server_type == RTSP_SERVER_WMS ||
(rt->server_type != RTSP_SERVER_REAL &&
rt->get_parameter_supported)) {
ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
} else {
// ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL);//コード ff_rtsp_send_cmd_async(s, "OPTIONS", rt->control_uri, NULL);//修正後のコードは、ipcがGETをサポートしなくてもPARAMETERの命令はkeepaliveできます }
/* The stale flag should be reset when creating the auth response in
* ff_rtsp_send_cmd_async, but reset it here just in case we never
* called the auth code (if we didn't have any credentials set). */
rt->auth_state.stale = 0;
}
}
2:rtp/rtsp/tcp転送でstimout(socket timeout)が設定されていない場合、server断線後av_read_フレームが詰まる
折りたたむか開くかクリック
AVFormatContext *pFormatCtx = NULL;
AVPacket packet;
AVDictionary *optionsDict = NULL;
char *streamurl1 = "rtsp://test:[email protected]:554/test.stream";
// Register all formats and codecs
av_register_all();
avformat_network_init();
pFormatCtx = avformat_alloc_context();
av_dict_set(&optionsDict, "rtsp_transport", "tcp", 0);//tcp伝送採用
av_dict_set(&optionsDict, "stimeout", "2000000", 0);//stimeoutが設定されていない場合はipcケーブルを抜いてav_read_frameはブロックされます(時間単位は微妙です)
// Open video file
if(avformat_open_input(&pFormatCtx, streamurl, NULL, &optionsDict)!=0){
printf("linesize = %d", __LINE__);
return -1; // Couldn't open file
}
// Retrieve stream information
if(avformat_find_stream_info(pFormatCtx, NULL)<0){
printf("linesize = %d", __LINE__);
return -1; // Couldn't find stream information
}
// Find the first video stream
int videoStream=-1;
for(i=0; i
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
videoStream=i;
break;
}
}
if(videoStream==-1){
printf("linesize = %d", __LINE__);
return -1; // Didn't find a video stream
}
// Read frames and save first five frames to disk
while(av_read_frame(pFormatCtx, &packet)>=0) {
av_free_packet(&packet);
}
ffmpeg 2なら.0.1バージョンなら、一言追加すればOKです.しかし旧バージョンffmpeg 1.2.*stimeoutというフィールドが設定されていないので、自分で追加するしかありません.ffmpeg/libavformat/rtsp.h struct RTSPState stimeoutフィールドを追加
折りたたむか開くかクリック
typedef struct RTSPState {
/**
* timeout of socket i/o operations.(this version do not have this segment. added by yqing, refer to ffmpeg-2.0.1)
*/
int stimeout;
} RTSPState;
ffmpeg/libavformat/rtsp.c ff_rtsp_options stimeoutフィールドを追加
折りたたむか開くかクリック
const AVOption ff_rtsp_options[] = {
{ "stimeout", "timeout (in micro seconds) of socket i/o operations.", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX,DEC},//この行のコードを追加
RTSP_REORDERING_OPTS(),
{ NULL },
};
ffmpeg/libavformat/rtsp.c ff_rtsp_connect関数の変更部分のコードは以下の通りです.
折りたたむか開くかクリック
//ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);//コード ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, "?timeout=%d", rt->stimeout);//修正後のコード