안녕하세요. ffmpeg으로 rtsp 관련 공부를 하고있습니다.
안드로이드에서 ffmpeg으로 rtsp 재생까지는 제대로 되더군요..
근데 오픈 무비후, 클로즈 무비를 할 때 메모리 프리 하는부분이 충돌이 일어나더군요.
여러가지 시도를 해봤지만.. 아니다 싶어서 질문 드립니다.
rtsp로 ffmpeg 오픈무비할때 close하는 방법이 따로 있나요?
아래 코드가 오프라인 소스코드이긴 한데.. 뭔가 바꾸어 주어야할 부분이 있나요?
한가지 더 의심되는부분은 엑티비티에서 draw 해주면서 뿌리는데, 이 부분이랑도 뭔가 충돌이있어서 그럴까요?
(메모리 프리 충돌은 사용하고있기떄문에 충돌나는걸까요... 없으면 널에 걸려 들어가진 않을꺼같은데..)
코드를 수정해서 오류부분을 제거 하더라도 다 끝난후 에러가 나더군요...(아래소스코드에도 로그찍어봤습니다.)
Fatal signal 11 (SIGSEGV) at 0x8fc3878c (code=1), thread 12718
위 에러가 뜹니다. (수정 전, 후 모두)
동영상 코덱 관련은 공부를해도 어렵네요...
간단한 조언 이라도 좋으니 답변 부탁드립니다.
아래의 공개 코드를 이용하여 사용하고있습니다.
/*
* Main functions of BasicPlayer
* 2011-2011 Jaebong Lee (novaever@gmail.com)
*
* BasicPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "avcodec.h"
#include "avformat.h"
#include "swscale.h"
#include "BasicPlayer.h"
AVFormatContext *gFormatCtx = NULL;
AVCodecContext *gVideoCodecCtx = NULL;
AVCodec *gVideoCodec = NULL;
int gVideoStreamIdx = -1;
AVFrame *gFrame = NULL;
AVFrame *gFrameRGB = NULL;
struct SwsContext *gImgConvertCtx = NULL;
int gPictureSize = 0;
uint8_t *gVideoBuffer = NULL;
int openMovie(const char filePath[])
{
int i;
if (gFormatCtx != NULL)
return -1;
if (av_open_input_file(&gFormatCtx, filePath, NULL, 0, NULL) != 0)
return -2;
if (av_find_stream_info(gFormatCtx) < 0)
return -3;
for (i = 0; i < gFormatCtx->nb_streams; i++) {
if (gFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
gVideoStreamIdx = i;
break;
}
}
if (gVideoStreamIdx == -1)
return -4;
gVideoCodecCtx = gFormatCtx->streams[gVideoStreamIdx]->codec;
gVideoCodec = avcodec_find_decoder(gVideoCodecCtx->codec_id);
if (gVideoCodec == NULL)
return -5;
if (avcodec_open(gVideoCodecCtx, gVideoCodec) < 0)
return -6;
gFrame = avcodec_alloc_frame();
if (gFrame == NULL)
return -7;
gFrameRGB = avcodec_alloc_frame();
if (gFrameRGB == NULL)
return -8;
gPictureSize = avpicture_get_size(PIX_FMT_RGB565LE, gVideoCodecCtx->width, gVideoCodecCtx->height);
gVideoBuffer = (uint8_t*)(malloc(sizeof(uint8_t) * gPictureSize));
avpicture_fill((AVPicture*)gFrameRGB, gVideoBuffer, PIX_FMT_RGB565LE, gVideoCodecCtx->width, gVideoCodecCtx->height);
return 0;
}
int decodeFrame()
{
int frameFinished = 0;
AVPacket packet;
while (av_read_frame(gFormatCtx, &packet) >= 0) {
if (packet.stream_index == gVideoStreamIdx) {
avcodec_decode_video2(gVideoCodecCtx, gFrame, &frameFinished, &packet);
if (frameFinished) {
gImgConvertCtx = sws_getCachedContext(gImgConvertCtx,
gVideoCodecCtx->width, gVideoCodecCtx->height, gVideoCodecCtx->pix_fmt,
gVideoCodecCtx->width, gVideoCodecCtx->height, PIX_FMT_RGB565LE, SWS_BICUBIC, NULL, NULL, NULL);
sws_scale(gImgConvertCtx, gFrame->data, gFrame->linesize, 0, gVideoCodecCtx->height, gFrameRGB->data, gFrameRGB->linesize);
av_free_packet(&packet);
return 0;
}
}
av_free_packet(&packet);
}
return -1;
}
void copyPixels(uint8_t *pixels)
{
memcpy(pixels, gFrameRGB->data[0], gPictureSize);
}
int getWidth()
{
return gVideoCodecCtx->width;
}
int getHeight()
{
return gVideoCodecCtx->height;
}
void closeMovie()
{
if (gVideoBuffer != NULL) {
free(gVideoBuffer);
gVideoBuffer = NULL;
}
if (gFrame != NULL)
av_freep(gFrame);
if (gFrameRGB != NULL)
av_freep(gFrameRGB);
if (gVideoCodecCtx != NULL) {
avcodec_close(gVideoCodecCtx);
gVideoCodecCtx = NULL;
}
if (gFormatCtx != NULL) {
av_close_input_file(gFormatCtx);
gFormatCtx = NULL;
}
}