[ffmpeg] ffmpeg 4.1 이상 버전의 비디오 스트림 읽기

spring·2020년 11월 9일
0

ffmpeg은 4.1버전부터 API가 완전히 변경되었다. 기존의 API는 deprecated되었고 컴파일러 옵션을 통해 사용이 가능하긴 하나, deprecated가 되었으면 언젠가 사라질 예정이므로 새로운 API를 정리해서 올려둔다.

ffmpeg이라고 하면 보통 바이너리만 사용하여 직접 빌드해야 하지만, 아래 주소를 통해 미리 빌드된 버전을 받아서 C코드로 작성이 가능하다.

https://ffmpeg.zeranoe.com/builds/

ffmpeg 코드를 구현할 때는 반복문 안에서 메모리 해제에 유의해야 한다. C언어 library인 만큼 메모리 해제는 모두 본인의 몫이다.

모든 객체는 해제를 해야함이 원칙이고 팁을 하나 적자면

뒤에 undef가 붙은 해제 함수는 내부 할당 메모리를 해제하는 것이고,
뒤에 free가 붙은 해제 함수는 그 자체를 해제하는 것이다.
즉 둘다 써야 한다. undef가 없으면 free만 사용하면 된다.

#ifdef __cplusplus
extern "C" {
#endif
#include<libavformat/avformat.h>
#include<libswscale/swscale.h>
#include<libavutil/imgutils.h>
#ifdef __cplusplus
}
#endif
int main() {
	const char* video_address = "rtsp://b1.dnsdojo.com:1935/live/sys2.stream";
	AVDictionary *dicts = NULL;
	//TCP를 사용해야 영상의 손실을 막을 수 있다. 기본값은 UDP
	av_dict_set(&dicts, "rtsp_transport", "tcp", 0);			
	AVFormatContext* av_fmt_ctx= avformat_alloc_context();
	if (avformat_open_input(&av_fmt_ctx, video_address, NULL, &dicts) != 0) return 1;
	if (avformat_find_stream_info(av_fmt_ctx, NULL) < 0) return 1;
	AVStream* stream = NULL;
	for (unsigned int i = 0; i < av_fmt_ctx->nb_streams; i++) {
		if (av_fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
			stream = av_fmt_ctx->streams[i];
			break;
		}
	}
	AVCodecContext* av_cdc_ctx = avcodec_alloc_context3(NULL);
	avcodec_parameters_to_context(av_cdc_ctx, stream->codecpar);
	//HW에 적합한 코덱을 자동으로 찾아 준다.
	AVCodec* av_cdc = avcodec_find_decoder(av_cdc_ctx->codec_id);
	avcodec_open2(av_cdc_ctx, av_cdc, NULL);
	AVPacket* av_pkt = av_packet_alloc();
	av_init_packet(av_pkt);
	AVFrame* av_frame = av_frame_alloc();

	while (1) {
		av_frame_unref(av_frame);
		int r = 0;
		do {
			do {
				av_packet_unref(av_pkt);
				r = av_read_frame(av_fmt_ctx, av_pkt);
			} while (av_pkt->stream_index != stream->index);
			avcodec_send_packet(av_cdc_ctx, av_pkt);
			r = avcodec_receive_frame(av_cdc_ctx, av_frame);
			av_packet_unref(av_pkt);
			if (r == AVERROR_EOF) goto EOV;
		} while (r != 0);
	}
EOV:
    av_packet_unref(av_pkt);
	av_packet_free(&av_pkt);
	av_frame_free(&av_frame);
	avcodec_free_context(&av_cdc_ctx);
	avformat_free_context(av_fmt_ctx);
	av_dict_free(&dicts);
	return 0;
}
profile
Researcher & Developer @ NAVER Corp | Designer @ HONGIK Univ.

0개의 댓글