마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

안드로이드 ffmpeg rtsp 관련 질문드립니다.

0 추천

안녕하세요. 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;
	}
}

 

김쿠마 (270 포인트) 님이 2014년 11월 27일 질문

1개의 답변

0 추천
내용을 잘못 적어 지웠습니다.
익명사용자 님이 2015년 9월 4일 답변
2015년 9월 7일 수정
...