Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
E
evsuits
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
OpsTeam
evsuits
Commits
b092120a
提交
b092120a
authored
8月 03, 2019
作者:
blu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
init
上级
2bbecf82
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
255 行增加
和
414 行删除
+255
-414
Makefile
opencv-motion-detect/Makefile
+8
-5
rtsp.c
opencv-motion-detect/rtsp.c
+0
-261
rtsp.cpp
opencv-motion-detect/rtsp.cpp
+247
-148
没有找到文件。
opencv-motion-detect/Makefile
浏览文件 @
b092120a
...
...
@@ -11,10 +11,13 @@ OPENCV = `pkg-config opencv --cflags --libs`
FFMPEG
=
`
pkg-config libavformat libavutil libavcodec
--cflags
--libs
`
all
:
cvprog mux rtsp
all
:
cvprog mux rtsp
rtspr
rtsp
:
rtsp.c
$(CC)
$(CFLAGS)
-o
rtsp rtsp.c
$(FFMPEG)
rtspr
:
rtsp-relay.cpp
$(CPP)
$(CFLAGS)
-o
rtspr rtsp-relay.cpp
$(FFMPEG)
rtsp
:
rtsp.cpp
$(CPP)
$(CFLAGS)
-o
rtsp rtsp.cpp
$(FFMPEG)
cvprog
:
prog1.cpp
$(CPP)
$(CPPFLAGS)
-o
$(cvprog)
$(cvsrc)
$(OPENCV)
...
...
@@ -23,4 +26,4 @@ mux:demuxing_decoding.c
$(CC)
$(CFLAGS)
-o
mux demuxing_decoding.c
$(FFMPEG)
clean
:
rm
-fr
rtsp cvprog mux
\ No newline at end of file
rm
-fr
rtsp cvprog mux rtspr
\ No newline at end of file
opencv-motion-detect/rtsp.c
deleted
100644 → 0
浏览文件 @
2bbecf82
/*
* http://ffmpeg.org/doxygen/trunk/index.html
*
* Main components
*
* Format (Container) - a wrapper, providing sync, metadata and muxing for the streams.
* Stream - a continuous stream (audio or video) of data over time.
* Codec - defines how data are enCOded (from Frame to Packet)
* and DECoded (from Packet to Frame).
* Packet - are the data (kind of slices of the stream data) to be decoded as raw frames.
* Frame - a decoded raw frame (to be encoded or filtered).
*/
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
// print out the steps and errors
static
void
logging
(
const
char
*
fmt
,
...);
// decode packets into frames
static
int
decode_packet
(
AVPacket
*
pPacket
,
AVCodecContext
*
pCodecContext
,
AVFrame
*
pFrame
);
// save a frame into a .pgm file
static
void
save_gray_frame
(
unsigned
char
*
buf
,
int
wrap
,
int
xsize
,
int
ysize
,
char
*
filename
);
int
main
(
int
argc
,
const
char
*
argv
[])
{
logging
(
"initializing all the containers, codecs and protocols."
);
// AVFormatContext holds the header information from the format (Container)
// Allocating memory for this component
// http://ffmpeg.org/doxygen/trunk/structAVFormatContext.html
AVFormatContext
*
pFormatContext
=
avformat_alloc_context
();
if
(
!
pFormatContext
)
{
logging
(
"ERROR could not allocate memory for Format Context"
);
return
-
1
;
}
logging
(
"opening the input file (%s) and loading format (container) header"
,
argv
[
1
]);
// Open the file and read its header. The codecs are not opened.
// The function arguments are:
// AVFormatContext (the component we allocated memory for),
// url (filename),
// AVInputFormat (if you pass NULL it'll do the auto detect)
// and AVDictionary (which are options to the demuxer)
// http://ffmpeg.org/doxygen/trunk/group__lavf__decoding.html#ga31d601155e9035d5b0e7efedc894ee49
if
(
avformat_open_input
(
&
pFormatContext
,
argv
[
1
],
NULL
,
NULL
)
!=
0
)
{
logging
(
"ERROR could not open the file"
);
return
-
1
;
}
// now we have access to some information about our file
// since we read its header we can say what format (container) it's
// and some other information related to the format itself.
logging
(
"format %s, duration %lld us, bit_rate %lld"
,
pFormatContext
->
iformat
->
name
,
pFormatContext
->
duration
,
pFormatContext
->
bit_rate
);
logging
(
"finding stream info from format"
);
// read Packets from the Format to get stream information
// this function populates pFormatContext->streams
// (of size equals to pFormatContext->nb_streams)
// the arguments are:
// the AVFormatContext
// and options contains options for codec corresponding to i-th stream.
// On return each dictionary will be filled with options that were not found.
// https://ffmpeg.org/doxygen/trunk/group__lavf__decoding.html#gad42172e27cddafb81096939783b157bb
if
(
avformat_find_stream_info
(
pFormatContext
,
NULL
)
<
0
)
{
logging
(
"ERROR could not get the stream info"
);
return
-
1
;
}
// the component that knows how to enCOde and DECode the stream
// it's the codec (audio or video)
// http://ffmpeg.org/doxygen/trunk/structAVCodec.html
AVCodec
*
pCodec
=
NULL
;
// this component describes the properties of a codec used by the stream i
// https://ffmpeg.org/doxygen/trunk/structAVCodecParameters.html
AVCodecParameters
*
pCodecParameters
=
NULL
;
int
video_stream_index
=
-
1
;
// loop though all the streams and print its main information
for
(
int
i
=
0
;
i
<
pFormatContext
->
nb_streams
;
i
++
)
{
AVCodecParameters
*
pLocalCodecParameters
=
NULL
;
pLocalCodecParameters
=
pFormatContext
->
streams
[
i
]
->
codecpar
;
logging
(
"AVStream->time_base before open coded %d/%d"
,
pFormatContext
->
streams
[
i
]
->
time_base
.
num
,
pFormatContext
->
streams
[
i
]
->
time_base
.
den
);
logging
(
"AVStream->r_frame_rate before open coded %d/%d"
,
pFormatContext
->
streams
[
i
]
->
r_frame_rate
.
num
,
pFormatContext
->
streams
[
i
]
->
r_frame_rate
.
den
);
logging
(
"AVStream->start_time %"
PRId64
,
pFormatContext
->
streams
[
i
]
->
start_time
);
logging
(
"AVStream->duration %"
PRId64
,
pFormatContext
->
streams
[
i
]
->
duration
);
logging
(
"finding the proper decoder (CODEC)"
);
AVCodec
*
pLocalCodec
=
NULL
;
// finds the registered decoder for a codec ID
// https://ffmpeg.org/doxygen/trunk/group__lavc__decoding.html#ga19a0ca553277f019dd5b0fec6e1f9dca
pLocalCodec
=
avcodec_find_decoder
(
pLocalCodecParameters
->
codec_id
);
if
(
pLocalCodec
==
NULL
)
{
logging
(
"ERROR unsupported codec!"
);
return
-
1
;
}
// when the stream is a video we store its index, codec parameters and codec
if
(
pLocalCodecParameters
->
codec_type
==
AVMEDIA_TYPE_VIDEO
)
{
if
(
video_stream_index
==
-
1
)
{
video_stream_index
=
i
;
pCodec
=
pLocalCodec
;
pCodecParameters
=
pLocalCodecParameters
;
}
logging
(
"Video Codec: resolution %d x %d"
,
pLocalCodecParameters
->
width
,
pLocalCodecParameters
->
height
);
}
else
if
(
pLocalCodecParameters
->
codec_type
==
AVMEDIA_TYPE_AUDIO
)
{
logging
(
"Audio Codec: %d channels, sample rate %d"
,
pLocalCodecParameters
->
channels
,
pLocalCodecParameters
->
sample_rate
);
}
// print its name, id and bitrate
logging
(
"
\t
Codec %s ID %d bit_rate %lld"
,
pLocalCodec
->
name
,
pLocalCodec
->
id
,
pCodecParameters
->
bit_rate
);
}
// https://ffmpeg.org/doxygen/trunk/structAVCodecContext.html
AVCodecContext
*
pCodecContext
=
avcodec_alloc_context3
(
pCodec
);
if
(
!
pCodecContext
)
{
logging
(
"failed to allocated memory for AVCodecContext"
);
return
-
1
;
}
// Fill the codec context based on the values from the supplied codec parameters
// https://ffmpeg.org/doxygen/trunk/group__lavc__core.html#gac7b282f51540ca7a99416a3ba6ee0d16
if
(
avcodec_parameters_to_context
(
pCodecContext
,
pCodecParameters
)
<
0
)
{
logging
(
"failed to copy codec params to codec context"
);
return
-
1
;
}
// Initialize the AVCodecContext to use the given AVCodec.
// https://ffmpeg.org/doxygen/trunk/group__lavc__core.html#ga11f785a188d7d9df71621001465b0f1d
if
(
avcodec_open2
(
pCodecContext
,
pCodec
,
NULL
)
<
0
)
{
logging
(
"failed to open codec through avcodec_open2"
);
return
-
1
;
}
// https://ffmpeg.org/doxygen/trunk/structAVFrame.html
AVFrame
*
pFrame
=
av_frame_alloc
();
if
(
!
pFrame
)
{
logging
(
"failed to allocated memory for AVFrame"
);
return
-
1
;
}
// https://ffmpeg.org/doxygen/trunk/structAVPacket.html
AVPacket
*
pPacket
=
av_packet_alloc
();
if
(
!
pPacket
)
{
logging
(
"failed to allocated memory for AVPacket"
);
return
-
1
;
}
int
response
=
0
;
int
how_many_packets_to_process
=
8
;
// fill the Packet with data from the Stream
// https://ffmpeg.org/doxygen/trunk/group__lavf__decoding.html#ga4fdb3084415a82e3810de6ee60e46a61
while
(
av_read_frame
(
pFormatContext
,
pPacket
)
>=
0
)
{
// if it's the video stream
if
(
pPacket
->
stream_index
==
video_stream_index
)
{
logging
(
"AVPacket->pts %"
PRId64
,
pPacket
->
pts
);
response
=
decode_packet
(
pPacket
,
pCodecContext
,
pFrame
);
if
(
response
<
0
){
// logging("decode_packet error: %s", av_err2str(response));
continue
;
}
// stop it, otherwise we'll be saving hundreds of frames
if
(
--
how_many_packets_to_process
<=
0
)
break
;
}
// https://ffmpeg.org/doxygen/trunk/group__lavc__packet.html#ga63d5a489b419bd5d45cfd09091cbcbc2
av_packet_unref
(
pPacket
);
}
logging
(
"releasing all the resources"
);
avformat_close_input
(
&
pFormatContext
);
avformat_free_context
(
pFormatContext
);
av_packet_free
(
&
pPacket
);
av_frame_free
(
&
pFrame
);
avcodec_free_context
(
&
pCodecContext
);
return
0
;
}
static
void
logging
(
const
char
*
fmt
,
...)
{
va_list
args
;
fprintf
(
stderr
,
"LOG: "
);
va_start
(
args
,
fmt
);
vfprintf
(
stderr
,
fmt
,
args
);
va_end
(
args
);
fprintf
(
stderr
,
"
\n
"
);
}
static
int
decode_packet
(
AVPacket
*
pPacket
,
AVCodecContext
*
pCodecContext
,
AVFrame
*
pFrame
)
{
// Supply raw packet data as input to a decoder
// https://ffmpeg.org/doxygen/trunk/group__lavc__decoding.html#ga58bc4bf1e0ac59e27362597e467efff3
int
response
=
avcodec_send_packet
(
pCodecContext
,
pPacket
);
int
ret
=
-
1
;
if
(
response
<
0
)
{
logging
(
"Error while sending a packet to the decoder: %s"
,
av_err2str
(
response
));
return
response
;
}
while
(
response
>=
0
)
{
// Return decoded output data (into a frame) from a decoder
// https://ffmpeg.org/doxygen/trunk/group__lavc__decoding.html#ga11e6542c4e66d3028668788a1a74217c
response
=
avcodec_receive_frame
(
pCodecContext
,
pFrame
);
if
(
response
==
AVERROR
(
EAGAIN
)
||
response
==
AVERROR_EOF
)
{
//frame packet consumed, read next frame from AVFormatContext
// logging("Error response: %s", av_err2str(response));
// response = 0;
// no frame extraced
break
;
}
if
(
response
<
0
)
{
logging
(
"Error while receiving a frame from the decoder: %s"
,
av_err2str
(
response
));
return
response
;
}
else
{
logging
(
"Frame %d (type=%c, size=%d bytes) pts %d key_frame %d [DTS %d]"
,
pCodecContext
->
frame_number
,
av_get_picture_type_char
(
pFrame
->
pict_type
),
pFrame
->
pkt_size
,
pFrame
->
pts
,
pFrame
->
key_frame
,
pFrame
->
coded_picture_number
);
char
frame_filename
[
1024
];
snprintf
(
frame_filename
,
sizeof
(
frame_filename
),
"%s-%d.pgm"
,
"frame"
,
pCodecContext
->
frame_number
);
// save a grayscale frame into a .pgm file
save_gray_frame
(
pFrame
->
data
[
0
],
pFrame
->
linesize
[
0
],
pFrame
->
width
,
pFrame
->
height
,
frame_filename
);
ret
=
0
;
}
}
return
ret
;
}
static
void
save_gray_frame
(
unsigned
char
*
buf
,
int
wrap
,
int
xsize
,
int
ysize
,
char
*
filename
)
{
FILE
*
f
;
int
i
;
f
=
fopen
(
filename
,
"w"
);
// writing the minimal required header for a pgm file format
// portable graymap format -> https://en.wikipedia.org/wiki/Netpbm_format#PGM_example
fprintf
(
f
,
"P5
\n
%d %d
\n
%d
\n
"
,
xsize
,
ysize
,
255
);
// writing line by line
for
(
i
=
0
;
i
<
ysize
;
i
++
)
fwrite
(
buf
+
i
*
wrap
,
1
,
xsize
,
f
);
fclose
(
f
);
}
opencv-motion-detect/rtsp.cpp
浏览文件 @
b092120a
#include <stdlib.h>
/*
* http://ffmpeg.org/doxygen/trunk/index.html
*
* Main components
*
* Format (Container) - a wrapper, providing sync, metadata and muxing for the streams.
* Stream - a continuous stream (audio or video) of data over time.
* Codec - defines how data are enCOded (from Frame to Packet)
* and DECoded (from Packet to Frame).
* Packet - are the data (kind of slices of the stream data) to be decoded as raw frames.
* Frame - a decoded raw frame (to be encoded or filtered).
*/
extern
"C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <sys/time.h>
}
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
// print out the steps and errors
static
void
logging
(
const
char
*
fmt
,
...);
// decode packets into frames
static
int
decode_packet
(
AVPacket
*
pPacket
,
AVCodecContext
*
pCodecContext
,
AVFrame
*
pFrame
);
// save a frame into a .pgm file
static
void
save_gray_frame
(
unsigned
char
*
buf
,
int
wrap
,
int
xsize
,
int
ysize
,
char
*
filename
);
time_t
get_time
(
)
int
main
(
int
argc
,
const
char
*
argv
[]
)
{
struct
timeval
tv
;
logging
(
"initializing all the containers, codecs and protocols."
);
// AVFormatContext holds the header information from the format (Container)
// Allocating memory for this component
// http://ffmpeg.org/doxygen/trunk/structAVFormatContext.html
AVFormatContext
*
pFormatContext
=
avformat_alloc_context
();
if
(
!
pFormatContext
)
{
logging
(
"ERROR could not allocate memory for Format Context"
);
return
-
1
;
}
logging
(
"opening the input file (%s) and loading format (container) header"
,
argv
[
1
]);
// Open the file and read its header. The codecs are not opened.
// The function arguments are:
// AVFormatContext (the component we allocated memory for),
// url (filename),
// AVInputFormat (if you pass NULL it'll do the auto detect)
// and AVDictionary (which are options to the demuxer)
// http://ffmpeg.org/doxygen/trunk/group__lavf__decoding.html#ga31d601155e9035d5b0e7efedc894ee49
if
(
avformat_open_input
(
&
pFormatContext
,
argv
[
1
],
NULL
,
NULL
)
!=
0
)
{
logging
(
"ERROR could not open the file"
);
return
-
1
;
}
gettimeofday
(
&
tv
,
NULL
);
// now we have access to some information about our file
// since we read its header we can say what format (container) it's
// and some other information related to the format itself.
logging
(
"format %s, duration %lld us, bit_rate %lld"
,
pFormatContext
->
iformat
->
name
,
pFormatContext
->
duration
,
pFormatContext
->
bit_rate
);
logging
(
"finding stream info from format"
);
// read Packets from the Format to get stream information
// this function populates pFormatContext->streams
// (of size equals to pFormatContext->nb_streams)
// the arguments are:
// the AVFormatContext
// and options contains options for codec corresponding to i-th stream.
// On return each dictionary will be filled with options that were not found.
// https://ffmpeg.org/doxygen/trunk/group__lavf__decoding.html#gad42172e27cddafb81096939783b157bb
if
(
avformat_find_stream_info
(
pFormatContext
,
NULL
)
<
0
)
{
logging
(
"ERROR could not get the stream info"
);
return
-
1
;
}
// the component that knows how to enCOde and DECode the stream
// it's the codec (audio or video)
// http://ffmpeg.org/doxygen/trunk/structAVCodec.html
AVCodec
*
pCodec
=
NULL
;
// this component describes the properties of a codec used by the stream i
// https://ffmpeg.org/doxygen/trunk/structAVCodecParameters.html
AVCodecParameters
*
pCodecParameters
=
NULL
;
int
video_stream_index
=
-
1
;
// loop though all the streams and print its main information
for
(
int
i
=
0
;
i
<
pFormatContext
->
nb_streams
;
i
++
)
{
AVCodecParameters
*
pLocalCodecParameters
=
NULL
;
pLocalCodecParameters
=
pFormatContext
->
streams
[
i
]
->
codecpar
;
logging
(
"AVStream->time_base before open coded %d/%d"
,
pFormatContext
->
streams
[
i
]
->
time_base
.
num
,
pFormatContext
->
streams
[
i
]
->
time_base
.
den
);
logging
(
"AVStream->r_frame_rate before open coded %d/%d"
,
pFormatContext
->
streams
[
i
]
->
r_frame_rate
.
num
,
pFormatContext
->
streams
[
i
]
->
r_frame_rate
.
den
);
logging
(
"AVStream->start_time %"
PRId64
,
pFormatContext
->
streams
[
i
]
->
start_time
);
logging
(
"AVStream->duration %"
PRId64
,
pFormatContext
->
streams
[
i
]
->
duration
);
logging
(
"finding the proper decoder (CODEC)"
);
AVCodec
*
pLocalCodec
=
NULL
;
// finds the registered decoder for a codec ID
// https://ffmpeg.org/doxygen/trunk/group__lavc__decoding.html#ga19a0ca553277f019dd5b0fec6e1f9dca
pLocalCodec
=
avcodec_find_decoder
(
pLocalCodecParameters
->
codec_id
);
if
(
pLocalCodec
==
NULL
)
{
logging
(
"ERROR unsupported codec!"
);
return
-
1
;
}
// when the stream is a video we store its index, codec parameters and codec
if
(
pLocalCodecParameters
->
codec_type
==
AVMEDIA_TYPE_VIDEO
)
{
if
(
video_stream_index
==
-
1
)
{
video_stream_index
=
i
;
pCodec
=
pLocalCodec
;
pCodecParameters
=
pLocalCodecParameters
;
}
logging
(
"Video Codec: resolution %d x %d"
,
pLocalCodecParameters
->
width
,
pLocalCodecParameters
->
height
);
}
else
if
(
pLocalCodecParameters
->
codec_type
==
AVMEDIA_TYPE_AUDIO
)
{
logging
(
"Audio Codec: %d channels, sample rate %d"
,
pLocalCodecParameters
->
channels
,
pLocalCodecParameters
->
sample_rate
);
}
// print its name, id and bitrate
logging
(
"
\t
Codec %s ID %d bit_rate %lld"
,
pLocalCodec
->
name
,
pLocalCodec
->
id
,
pCodecParameters
->
bit_rate
);
}
// https://ffmpeg.org/doxygen/trunk/structAVCodecContext.html
AVCodecContext
*
pCodecContext
=
avcodec_alloc_context3
(
pCodec
);
if
(
!
pCodecContext
)
{
logging
(
"failed to allocated memory for AVCodecContext"
);
return
-
1
;
}
return
tv
.
tv_sec
;
}
// Fill the codec context based on the values from the supplied codec parameters
// https://ffmpeg.org/doxygen/trunk/group__lavc__core.html#gac7b282f51540ca7a99416a3ba6ee0d16
if
(
avcodec_parameters_to_context
(
pCodecContext
,
pCodecParameters
)
<
0
)
{
logging
(
"failed to copy codec params to codec context"
);
return
-
1
;
}
int
main
(
int
argc
,
char
*
argv
[]
)
{
AVFormatContext
*
ifcx
=
NULL
;
AVInputFormat
*
ifmt
;
AVCodecContext
*
iccx
;
AVCodec
*
icodec
;
AVStream
*
ist
;
int
i_index
;
time_t
timenow
,
timestart
;
int
got_key_frame
=
0
;
AVFormatContext
*
ofcx
;
AVOutputFormat
*
ofmt
;
AVCodecContext
*
occx
;
AVCodec
*
ocodec
;
AVStream
*
ost
;
int
o_index
;
AVPacket
pkt
;
int
ix
;
const
char
*
sProg
=
argv
[
0
];
const
char
*
sFileInput
;
const
char
*
sFileOutput
;
int
bRunTime
;
if
(
argc
!=
4
)
{
printf
(
"Usage: %s url outfile runtime
\n
"
,
sProg
);
return
EXIT_FAILURE
;
}
sFileInput
=
argv
[
1
];
sFileOutput
=
argv
[
2
];
bRunTime
=
atoi
(
argv
[
3
]
);
// Initialize library
av_log_set_level
(
AV_LOG_DEBUG
);
// av_register_all();
// avcodec_register_all();
avformat_network_init
();
//
// Input
//
//open rtsp
if
(
avformat_open_input
(
&
ifcx
,
sFileInput
,
NULL
,
NULL
)
!=
0
)
{
printf
(
"ERROR: Cannot open input file
\n
"
);
return
EXIT_FAILURE
;
}
if
(
avformat_find_stream_info
(
ifcx
,
NULL
)
<
0
)
{
printf
(
"ERROR: Cannot find stream info
\n
"
);
avformat_close_input
(
&
ifcx
);
return
EXIT_FAILURE
;
}
snprintf
(
ifcx
->
filename
,
sizeof
(
ifcx
->
filename
),
"%s"
,
sFileInput
);
//search video stream
i_index
=
-
1
;
for
(
ix
=
0
;
ix
<
ifcx
->
nb_streams
;
ix
++
)
{
iccx
=
ifcx
->
streams
[
ix
]
->
codec
;
if
(
iccx
->
codec_type
==
AVMEDIA_TYPE_VIDEO
)
{
ist
=
ifcx
->
streams
[
ix
];
i_index
=
ix
;
break
;
// Initialize the AVCodecContext to use the given AVCodec.
// https://ffmpeg.org/doxygen/trunk/group__lavc__core.html#ga11f785a188d7d9df71621001465b0f1d
if
(
avcodec_open2
(
pCodecContext
,
pCodec
,
NULL
)
<
0
)
{
logging
(
"failed to open codec through avcodec_open2"
);
return
-
1
;
}
}
if
(
i_index
<
0
)
{
printf
(
"ERROR: Cannot find input video stream
\n
"
);
avformat_close_input
(
&
ifcx
);
return
EXIT_FAILURE
;
}
//
// Output
//
//open output file
ofmt
=
av_guess_format
(
NULL
,
sFileOutput
,
NULL
);
ofcx
=
avformat_alloc_context
();
ofcx
->
oformat
=
ofmt
;
avio_open2
(
&
ofcx
->
pb
,
sFileOutput
,
AVIO_FLAG_WRITE
,
NULL
,
NULL
);
// Create output stream
//ost = avformat_new_stream( ofcx, (AVCodec *) iccx->codec );
ost
=
avformat_new_stream
(
ofcx
,
NULL
);
avcodec_copy_context
(
ost
->
codec
,
iccx
);
ost
->
sample_aspect_ratio
.
num
=
iccx
->
sample_aspect_ratio
.
num
;
ost
->
sample_aspect_ratio
.
den
=
iccx
->
sample_aspect_ratio
.
den
;
// Assume r_frame_rate is accurate
ost
->
r_frame_rate
=
ist
->
r_frame_rate
;
ost
->
avg_frame_rate
=
ost
->
r_frame_rate
;
ost
->
time_base
=
av_inv_q
(
ost
->
r_frame_rate
);
ost
->
codec
->
time_base
=
ost
->
time_base
;
avformat_write_header
(
ofcx
,
NULL
);
snprintf
(
ofcx
->
filename
,
sizeof
(
ofcx
->
filename
),
"%s"
,
sFileOutput
);
//start reading packets from stream and write them to file
av_dump_format
(
ifcx
,
0
,
ifcx
->
filename
,
0
);
av_dump_format
(
ofcx
,
0
,
ofcx
->
filename
,
1
);
timestart
=
timenow
=
get_time
();
ix
=
0
;
//av_read_play(context);//play RTSP (Shouldn't need this since it defaults to playing on connect)
av_init_packet
(
&
pkt
);
while
(
av_read_frame
(
ifcx
,
&
pkt
)
>=
0
&&
timenow
-
timestart
<=
bRunTime
)
{
if
(
pkt
.
stream_index
==
i_index
)
{
//packet is video
// Make sure we start on a key frame
if
(
timestart
==
timenow
&&
!
(
pkt
.
flags
&
AV_PKT_FLAG_KEY
)
)
{
timestart
=
timenow
=
get_time
();
continue
;
}
got_key_frame
=
1
;
pkt
.
stream_index
=
ost
->
id
;
pkt
.
pts
=
ix
++
;
pkt
.
dts
=
pkt
.
pts
;
av_interleaved_write_frame
(
ofcx
,
&
pkt
);
// https://ffmpeg.org/doxygen/trunk/structAVFrame.html
AVFrame
*
pFrame
=
av_frame_alloc
();
if
(
!
pFrame
)
{
logging
(
"failed to allocated memory for AVFrame"
);
return
-
1
;
}
// https://ffmpeg.org/doxygen/trunk/structAVPacket.html
AVPacket
*
pPacket
=
av_packet_alloc
();
if
(
!
pPacket
)
{
logging
(
"failed to allocated memory for AVPacket"
);
return
-
1
;
}
int
response
=
0
;
// fill the Packet with data from the Stream
// https://ffmpeg.org/doxygen/trunk/group__lavf__decoding.html#ga4fdb3084415a82e3810de6ee60e46a61
while
(
av_read_frame
(
pFormatContext
,
pPacket
)
>=
0
)
{
// if it's the video stream
if
(
pPacket
->
stream_index
==
video_stream_index
)
{
logging
(
"AVPacket->pts %"
PRId64
,
pPacket
->
pts
);
response
=
decode_packet
(
pPacket
,
pCodecContext
,
pFrame
);
if
(
response
<
0
){
// logging("decode_packet error: %s", av_err2str(response));
continue
;
}
// stop it, otherwise we'll be saving hundreds of frames
// TODO: stop
}
// https://ffmpeg.org/doxygen/trunk/group__lavc__packet.html#ga63d5a489b419bd5d45cfd09091cbcbc2
av_packet_unref
(
pPacket
);
}
logging
(
"releasing all the resources"
);
avformat_close_input
(
&
pFormatContext
);
avformat_free_context
(
pFormatContext
);
av_packet_free
(
&
pPacket
);
av_frame_free
(
&
pFrame
);
avcodec_free_context
(
&
pCodecContext
);
return
0
;
}
static
void
logging
(
const
char
*
fmt
,
...)
{
va_list
args
;
fprintf
(
stderr
,
"LOG: "
);
va_start
(
args
,
fmt
);
vfprintf
(
stderr
,
fmt
,
args
);
va_end
(
args
);
fprintf
(
stderr
,
"
\n
"
);
}
static
int
decode_packet
(
AVPacket
*
pPacket
,
AVCodecContext
*
pCodecContext
,
AVFrame
*
pFrame
)
{
// Supply raw packet data as input to a decoder
// https://ffmpeg.org/doxygen/trunk/group__lavc__decoding.html#ga58bc4bf1e0ac59e27362597e467efff3
int
response
=
avcodec_send_packet
(
pCodecContext
,
pPacket
);
int
ret
=
-
1
;
if
(
response
<
0
)
{
logging
(
"Error while sending a packet to the decoder: %s"
,
av_err2str
(
response
));
return
response
;
}
av_free_packet
(
&
pkt
);
av_init_packet
(
&
pkt
);
timenow
=
get_time
();
}
av_read_pause
(
ifcx
);
av_write_trailer
(
ofcx
);
avio_close
(
ofcx
->
pb
);
avformat_free_context
(
ofcx
);
while
(
response
>=
0
)
{
// Return decoded output data (into a frame) from a decoder
// https://ffmpeg.org/doxygen/trunk/group__lavc__decoding.html#ga11e6542c4e66d3028668788a1a74217c
response
=
avcodec_receive_frame
(
pCodecContext
,
pFrame
);
if
(
response
==
AVERROR
(
EAGAIN
)
||
response
==
AVERROR_EOF
)
{
//frame packet consumed, read next frame from AVFormatContext
// logging("Error response: %s", av_err2str(response));
// response = 0;
// no frame extraced
break
;
}
if
(
response
<
0
)
{
logging
(
"Error while receiving a frame from the decoder: %s"
,
av_err2str
(
response
));
return
response
;
}
else
{
logging
(
"Frame %d (type=%c, size=%d bytes) pts %d key_frame %d [DTS %d]"
,
pCodecContext
->
frame_number
,
av_get_picture_type_char
(
pFrame
->
pict_type
),
pFrame
->
pkt_size
,
pFrame
->
pts
,
pFrame
->
key_frame
,
pFrame
->
coded_picture_number
);
char
frame_filename
[
1024
];
snprintf
(
frame_filename
,
sizeof
(
frame_filename
),
"%s-%d.pgm"
,
"frame"
,
pCodecContext
->
frame_number
);
// save a grayscale frame into a .pgm file
save_gray_frame
(
pFrame
->
data
[
0
],
pFrame
->
linesize
[
0
],
pFrame
->
width
,
pFrame
->
height
,
frame_filename
);
ret
=
0
;
}
}
avformat_network_deinit
();
return
ret
;
}
return
EXIT_SUCCESS
;
}
\ No newline at end of file
static
void
save_gray_frame
(
unsigned
char
*
buf
,
int
wrap
,
int
xsize
,
int
ysize
,
char
*
filename
)
{
FILE
*
f
;
int
i
;
f
=
fopen
(
filename
,
"w"
);
// writing the minimal required header for a pgm file format
// portable graymap format -> https://en.wikipedia.org/wiki/Netpbm_format#PGM_example
fprintf
(
f
,
"P5
\n
%d %d
\n
%d
\n
"
,
xsize
,
ysize
,
255
);
// writing line by line
for
(
i
=
0
;
i
<
ysize
;
i
++
)
fwrite
(
buf
+
i
*
wrap
,
1
,
xsize
,
f
);
fclose
(
f
);
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论