일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Python
- 빅데이터
- 가상화
- 삼성전자 소프트웨어멤버십 SSM
- SSM
- 물걸레로봇청소기추천
- 삼성소프트웨어멤버십
- 구글 앱 엔진
- 인공지능
- 패턴 인식
- 나르왈프레오
- 신경회로망
- 증강현실
- 동아리
- 물걸레자동세척로봇청소기
- 하이퍼바이저
- hopfield network
- Google App Engine
- 멤버십
- 고려대학교
- Bidirectional Associative Memory
- BAM
- 신경망
- 삼성
- 패턴인식
- 갤럭시탭S8울트라
- Friendship
- NarwalFreo
- Neural Network
- 파이썬
- Today
- Total
정보공간_1
[3기 강북 김승현] ffmpeg 를 이용한 간단한 동영상 플레이어 제작 #3 본문
[3기 강북 김승현] ffmpeg 를 이용한 간단한 동영상 플레이어 제작 #3
알 수 없는 사용자 2013. 5. 6. 20:00안녕하세요 강북멤버십 김승현입니다.
이번 글 은 저번글에서 이어서 ffmpeg library를 이용해서 간단하게
동영상 플레이어 제작하기를 연재 해보겠습니다.
각 플렛폼에 종속되는 a/v 출력 부분을 제외한, ffmpeg를 이용한
디코딩을 어떻게 하는지를 연재 할 예정입니다.
ffplay.c를 해부하면 해당 버전의 ffmpeg 라이브러리의 사용법을 전부 알아
낼 수 있지만 좀더 쉽게 개발 하는 데에 본 포스트가 도움이 되었으면 하는 바람이 있습니다.
본 포스트는 ffmpeg 1.0 stable 버전을 기준으로 작성 되었습니다.
필자는 windows 환경에서 개발을 진행 하였습니다.
9. audio 디코딩
AVFrame AudioFrame; //디코딩 결과가 저장될 프레임
if(Packet.stream_index == nAudioStreamIdx) //전에 저장했던 stream index를 비교해서 audio 패킷을 분류한다.
{
int nRemainByte = Packet.size;
void * pOrgData = Packet.data;
while (nRemainByte > 0)
{
int got_frame = 0;
avcodec_get_frame_defaults(&AudioFrame);
int Decoded= avcodec_decode_audio4(pAudioCodecContext, &AudioFrame,&got_frame,&Packet);
//audio decoding !!
if(nDecoded < 0) //0보다 작은건 디코딩 실패이므로 패킷 무시
{
nRemainByte = 0;
Packet.data = (uint8_t *)pOrgData;
av_free_packet(&Packet);
continue;
}
nRemainByte -= nDecoded;
Packet.size -= nDecoded;
Packet.data += nDecoded;
if(nRemainByte <= 0) //packet 디코딩을 완료하면...
{
Packet.data = (uint8_t *)pOrgData;
av_free_packet(&Packet); //패킷 삭제
nRemainByte = 0;
}
if(got_frame) //FRAME 이 얻어짐!
{
이제 이 얻어진 frame을 출력 장치에 알맞는 포멧으로 변환 해야한다.
}
}
10. audio 변환
이제는 얻어진 frame을 알맞은 형식으로 변환합니다.
if(got_frame)
{
int nDataSize = av_samples_get_buffer_size(NULL, pAudioCodecContext->channels,
AudioFrame.nb_samples,
pAudioCodecContext->sample_fmt, 1); //디코딩된 audio data의 길이를 구함
if(pAudioCodecContext->sample_fmt != AV_SAMPLE_FMT_S16)
{
SwrContext * pAudioCvtContext;
pAudioCvtContext = NULL;
pAudioCvtContext = swr_alloc_set_opts(pAudioCvtContext,
pAudioCodecContext->channel_layout, AV_SAMPLE_FMT_S16,pAudioCodecContext->sample_rate,pAudioCodecContext->channel_layout, pAudioCodecContext->sample_fmt,pAudioCodecContext->sample_rate,0,0); //SwrContext를 생성한다. 여기서는 singed 16bits로 변환하고자 한다.
int err;
if ((err = swr_init(pAudioCvtContext)) < 0) { //초기화
if(err == AVERROR(EINVAL))
fprintf(stderr, "Failed to initialize the resampling context\n");
}
static uint8_t AudioCvtBuffer[AVCODEC_MAX_AUDIO_FRAME_SIZE]; //변환결과 저장되는 버퍼
uint8_t *out[] = {AudioCvtBuffer};
const uint8_t *in[] = {AudioFrame.data[0]};
uint8_t *ain[SWR_CH_MAX];
if(!av_sample_fmt_is_planar(pAudioCodecContext->sample_fmt))
{
ain[0] = AudioFrame.data[0];
}
else
{
ain[0] = AudioFrame.data[0]; //8.1ch대비 9개를 만들었다
ain[1] = AudioFrame.data[0];
ain[2] = AudioFrame.data[0];
ain[3] = AudioFrame.data[0];
ain[4] = AudioFrame.data[0];
ain[5] = AudioFrame.data[0];
ain[6] = AudioFrame.data[0];
ain[7] = AudioFrame.data[0];
ain[8] = AudioFrame.data[0];
}
swr_convert(pAudioCvtContext,out,AudioFrame.nb_samples,(const uint8_t *)ain,AudioFrame.nb_samples); //변환수행!
int nDataSize2 = av_samples_get_buffer_size(NULL, pAudioCodecContext->channels,
AudioFrame.nb_samples,
AV_SAMPLE_FMT_S16, 1); //결과 데이터 길이 구하기
memcpy(pBuffer,AudioCvtBuffer,nDataSize2); //결과 데이터 저장 pBuffer이 결과 값 저장 배열이다
}
else
{
memcpy(pBuffer,AudioFrame.data[0],nDataSize); //결과 데이터 저장 pBuffer이 결과 값 저장 배열이다 . 변환하지 않고 그냥 복사
}
}
다음 포스트에는...
seeking, 파일 끝 처리 등을 을 다룰 예정입니다!
....
'IT 놀이터 > Elite Member Tech & Talk' 카테고리의 다른 글
[3기 신촌 최기환] WPF 활용 - 시리얼 통신 (0) | 2013.05.10 |
---|---|
[3기 대전 김재원] Linux Kernel - Data Structure (2) (0) | 2013.05.09 |
[3기 강북 김승현] ffmpeg 를 이용한 간단한 동영상 플레이어 제작 #2 (0) | 2013.05.06 |
[3기 강남 정준호] Console & Shell 개발 (0) | 2013.05.06 |
[3기 강남 백정의] Flash에서 현재 화면을 서버에 저장 및 불러오기 (0) | 2013.05.06 |