[FFmpeg] 동영상 디코딩
2016. 8. 31. 11:34ㆍApplication Programming/FFmpeg
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | #include "Header.h" int main(void) { av_register_all(); //ffmpedg에서 지원되는 모든 Demuxer, Muxer, Codec, Protocol을 사용할 수 있도록 등록 //전체 코드에서 한 번 불러주면 된다! AVCodec * pVideoCodec; AVCodec * pAudioCodec; AVPacket packet; //인코딩 된 파일 데이터 AVCodecContext * m_Context; //어떻게 디코딩 할 것인지 AVFormatContext *pFormatCtx = NULL; int ret = avformat_open_input(&pFormatCtx, "C:\\Sample.mp4", NULL, NULL); //미디어 파일 열기 //파일의 헤더로 부터 파일 포맷에 대한 정보를 읽어낸 뒤 첫번째 인자 (AVFormatContext) 에 저장한다. //그 뒤의 인자들은 각각 Input Source (스트리밍 URL이나 파일경로), Input Format, demuxer의 추가옵션 이다. if (ret != 0) { av_log(NULL, AV_LOG_ERROR, "File Open Failed\n"); exit(-1); } //파일이 제대로 열리지 않는다면 실패했다는 로그와 함께 종료 av_log(NULL, AV_LOG_INFO, "File Open Success\n"); //콘솔창에 로그메시지를 띄운다 ret = avformat_find_stream_info(pFormatCtx, NULL); //열어놓은 미디어 파일의 스트림 정보를 가져온다 if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Fail to get Stream Inform\n"); exit(-1); } av_log(NULL, AV_LOG_INFO, "Get Stream Inform Success\n"); int VSI = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); int ASI = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, VSI, NULL, 0); //첫번째 인자 : 스트림을 가져오고자 하는 미디어 파일을 담고 있는 AVFormatContext 구조체 //두번째 인자 : 가져오고자 하는 스트림의 타입 //세번째 인자 : 특별히 지정하고자 하는 스트림의 인텍스 번호. -1일 경우 자동선택 //네번째 인자 : 연관된 스트림의 인덱스 번호. -1일 경우 가장 처음으로 만나는 타겟 스트림을 가져온다. //다섯번째 인자 : Decoder까지 함께 검색할지 말지. AV코덱 구조체의 주소를 넘기도록 되어있다. //마지막 인자 : 따로 flag가 지정되지 않음. 현재 사용되지 않는 부분. pVideoCodec = avcodec_find_decoder(pFormatCtx->streams[VSI]->codecpar->codec_id); if (pVideoCodec == NULL) { av_log(NULL, AV_LOG_ERROR, "No Decoder\n"); exit(-1); } pAudioCodec = avcodec_find_decoder(pFormatCtx->streams[ASI]->codecpar->codec_id); if (pAudioCodec == NULL) { av_log(NULL, AV_LOG_ERROR, "No Decoder\n"); exit(-1); } AVCodecContext *pVCtx = avcodec_alloc_context3(pVideoCodec); AVCodecContext *pACtx = avcodec_alloc_context3(pAudioCodec); if (avcodec_open2(pVCtx, pVideoCodec, NULL) < 0) { av_log(NULL, AV_LOG_ERROR, "Fail to Initialize Decoder\n"); exit(-1); } //avcodec_open2 : 디코더 정보를 찾을 수 있다면 AVContext에 그 정보를 넘겨줘서 Decoder를 초기화 함 //첫번째 인자 : AVCodecContext 구조체 //두번째 인자 : AVCodec 구조체 //세번째 인자 : 디코더 초기화에 필요한 추가 옵션. 비트레이트 정보나 스레트 사용여부를 정해줄 수 있다. if (avcodec_open2(pACtx, pAudioCodec, NULL) < 0) { av_log(NULL, AV_LOG_ERROR, "Fail to Initialize Decoder\n"); exit(-1); } AVFrame *pVFrame = NULL; AVFrame *pAFrame = NULL; // 디코딩의 결과로 얻은 데이터를 저장하는 구조체 // 위에서 인코딩의 결과가 packet이었던 것 처럼! int bGotPicture = 0; int bGotSound = 0; while (av_read_frame(pFormatCtx, &packet) >=0) {//파일로부터 인코딩 된 비디오/ 오디오 데이터를 읽어서 packet에 저장하는 함수 if (packet.stream_index == VSI) { // Decode Video if (!avcodec_receive_frame(pVCtx, pVFrame)) { //이미지 렌더링 준비 완료! } } else if (packet.stream_index == ASI) { // Decode Audio if (!avcodec_receive_frame(pACtx, pAFrame)) { //사운드 렌더링 준비 완료! } } av_packet_unref(&packet); //AVPacket의 경우 포인터타입으로 선언해서 사용하지 않음 //구조체 내에 data라는 포인터 변수가 있기 때문임! //따라서 다 사용하고 나서 Release해주어야 할 필요가 있음!! } avformat_close_input(&pFormatCtx); //열었던 미디어파일 닫기 system("pause"); return 0; } | cs |
http://egloos.zum.com/aslike/v/3091644 이곳을 참고했다!! 완전 잘 정리해주셔서 이해하기 수월했다
근데 버전업이 되어서 그런지 'AVStream::codec': was declared deprecated 라는 에러가 여러개 떴다!!
AVStream::codec은 AVCodecContext 라는 이름의 구조체이다.
codec->codec_id처럼 구조체의 멤버변수를 부르는 곳에서는 codec대신 codecpar를, codec 처럼 구조체 자체를 부르는 곳에서는 AVCodecContext객체를 따로 만들어 avcodec_alloc_context3(AVCodec) 을 넣어준 뒤에 사용했다!
그걸 수정하고 나니 avcodec_decode_video2와 avcodec_decode_audio4에서 같은 메시지가 뜨길래 찾아보니 이제 사용하지 않는 함수라 대신 avcodec_send_packet() 과 avcodec_recieve_frame()을 사용해야 한다고 한다.
(https://libav.org/documentation/doxygen/master/deprecated.html)
여기까지 디코딩은 마쳤다! 이제 디코딩으로 얻어낸 정보를 화면에 뿌려주면 된다
'Application Programming > FFmpeg' 카테고리의 다른 글
[FFmpeg] 기본 소스코드 (0) | 2016.08.30 |
---|---|
[FFmpeg] 환경 구축 (0) | 2016.08.27 |