출처 : http://frontjang.tistory.com/213
ffmpeg을 컴파일하는 도중 다음과 같은 오류가 나올경우 컴파일 옵션에 CXXFLAGS=-D__STDC_CONSTANT_MACROS
을 추가해 주면 된다. 아니면 헤더파일에 아래 항목을 추가해 줄수도 있다. ffmpeg 뿐 아니라 다른 프로젝트에서도 이 방법을 사용할 수 있다.
#ifdef __cplusplus
#define __STDC_CONSTANT_MACROS
#ifdef _STDINT_H
#undef _STDINT_H
#endif
# include <stdint.h>
#endif
출처 : Issue 11 - ffmpegsource - 'UINT64_C' was not declared in this scope - An FFmpeg based source library and Avisynth plugin for easy frame accurate access - Google Project Hosting
2011년 12월 27일 화요일
2011년 12월 22일 목요일
FFmpeg 가지고 H.263 인코딩하기..
출처 : http://iamlow.tistory.com/entry/FFmpeg-%EA%B0%80%EC%A7%80%EA%B3%A0-H263-%EC%9D%B8%EC%BD%94%EB%94%A9%ED%95%98%EA%B8%B0
이 글도 테스트 과정을 적었다.
0. 환경은 MPEG4 테스트와 동일
1. 설정도 동일하다. 그러나 실행시켜 보면 아래와 같은 메시지가 나타난다.
[h263 @ 0x91a3020] warning, clipping 1 dct coefficients to -127..127
2. 코드 검색
$ grep -R "dct coefficients to" ../../*
../../libavcodec/mpegvideo_enc.c: av_log(s->avctx, AV_LOG_INFO, "warning, clipping %d dct coefficients to %d..%d\n", overflow, minlevel, maxlevel);
3. 코드를 보자
$ vi ../../libavcodec/mpegvideo_enc.c
1461 if(overflow && s->avctx->mb_decision == FF_MB_DECISION_SIMPLE)
1462 av_log(s->avctx, AV_LOG_INFO, "warning, clipping %d dct coefficients to %d..%d\n", overflow, minlevel, maxlevel);
- ctags를 활용하여 "FF_MB_DECISION_SIMPLE" 추적..
2030 /**
2031 * macroblock decision mode
2032 * - encoding: Set by user.
2033 * - decoding: unused
2034 */
2035 int mb_decision;
2036 #define FF_MB_DECISION_SIMPLE 0 ///< uses mb_cmp
2037 #define FF_MB_DECISION_BITS 1 ///< chooses the one which needs the fewest bits
2038 #define FF_MB_DECISION_RD 2 ///< rate distortion
- mb_cmp 라는 주석을 보고 또 추적..
1836 * macroblock comparison function (not supported yet)
1837 * - encoding: Set by user.
1838 * - decoding: unused
1839 */
1840 int mb_cmp;
- not supported yet 이란다...
avctx->mb_decision = FF_MB_DECISION_SIMPLE;
avctx->mb_cmp = -127 ~ ... 127 설정;
테스트 결과 not supported yet 이 검증됨...ㅋㅋ
- FFmpeg 홈페이지에도 아래와 같은 문구가 있음.
`-mbd mode'
macroblock decision
이 글도 테스트 과정을 적었다.
0. 환경은 MPEG4 테스트와 동일
1. 설정도 동일하다. 그러나 실행시켜 보면 아래와 같은 메시지가 나타난다.
[h263 @ 0x91a3020] warning, clipping 1 dct coefficients to -127..127
2. 코드 검색
$ grep -R "dct coefficients to" ../../*
../../libavcodec/mpegvideo_enc.c: av_log(s->avctx, AV_LOG_INFO, "warning, clipping %d dct coefficients to %d..%d\n", overflow, minlevel, maxlevel);
3. 코드를 보자
$ vi ../../libavcodec/mpegvideo_enc.c
1461 if(overflow && s->avctx->mb_decision == FF_MB_DECISION_SIMPLE)
1462 av_log(s->avctx, AV_LOG_INFO, "warning, clipping %d dct coefficients to %d..%d\n", overflow, minlevel, maxlevel);
- ctags를 활용하여 "FF_MB_DECISION_SIMPLE" 추적..
2030 /**
2031 * macroblock decision mode
2032 * - encoding: Set by user.
2033 * - decoding: unused
2034 */
2035 int mb_decision;
2036 #define FF_MB_DECISION_SIMPLE 0 ///< uses mb_cmp
2037 #define FF_MB_DECISION_BITS 1 ///< chooses the one which needs the fewest bits
2038 #define FF_MB_DECISION_RD 2 ///< rate distortion
- mb_cmp 라는 주석을 보고 또 추적..
1836 * macroblock comparison function (not supported yet)
1837 * - encoding: Set by user.
1838 * - decoding: unused
1839 */
1840 int mb_cmp;
- not supported yet 이란다...
avctx->mb_decision = FF_MB_DECISION_SIMPLE;
avctx->mb_cmp = -127 ~ ... 127 설정;
테스트 결과 not supported yet 이 검증됨...ㅋㅋ
- FFmpeg 홈페이지에도 아래와 같은 문구가 있음.
- `0'
- FF_MB_DECISION_SIMPLE: Use mb_cmp (cannot change it yet in ffmpeg).
- `1'
- FF_MB_DECISION_BITS: Choose the one which needs the fewest bits.
- `2'
- FF_MB_DECISION_RD: rate distortion
4. MB_DECISION 이 뭔가 인터넷 검색...
매크로블럭을 결정하는 방법들 이라는데.. 영상처리와 관련된 약간은 난이도가 있는 부분인듯하다..
FF_MB_DECISION_BITS ==> 잘 모르겠음..
FF_MB_DECISION_RD ==> 이 녀석이 화질이 가장 좋다고 하나, 처리하는데 시간이 오래 걸린덴다.. (모든 MB를 검색하여 가장 좋은 MB 모드를 설정한다고 한다.) 인터넷에 검색하니 약자로 RDO(Rate-distortion Optimization) 라고 불린다.
아래처럼 설정하면 경고메시지가 사라지고 정상동작한다.
매크로블럭을 결정하는 방법들 이라는데.. 영상처리와 관련된 약간은 난이도가 있는 부분인듯하다..
FF_MB_DECISION_BITS ==> 잘 모르겠음..
FF_MB_DECISION_RD ==> 이 녀석이 화질이 가장 좋다고 하나, 처리하는데 시간이 오래 걸린덴다.. (모든 MB를 검색하여 가장 좋은 MB 모드를 설정한다고 한다.) 인터넷에 검색하니 약자로 RDO(Rate-distortion Optimization) 라고 불린다.
아래처럼 설정하면 경고메시지가 사라지고 정상동작한다.
avctx->mb_decision = FF_MB_DECISION_BITS; // or FF_MB_DECISION_RD;
이상!!!
그리고 비트레이트가 딱 떨어지게 영상이 인코딩되지는 않는다.
이상!!!
그리고 비트레이트가 딱 떨어지게 영상이 인코딩되지는 않는다.
* 참고로.. 영상확인은 VLC 플레이어를 사용하여 정상적으로 인코딩 되었는지 확인했다..
FFMPEG을 가지고 MPEG4 Video 영상 인코딩하기
출처 : http://iamlow.tistory.com/entry/FFMPEG%EC%9D%84-%EA%B0%80%EC%A7%80%EA%B3%A0-MPEG4-Video-%EC%98%81%EC%83%81-%EC%9D%B8%EC%BD%94%EB%94%A9%ED%95%98%EA%B8%B0
여기에는 테스트한 발자취를 남긴다. 따라서 삽질하는 과정도 포함되어 있다.
이 작업을 한 이유는 이전에 작업한 libx264 라이브러리가 안드로이드 플랫폼에서 영상을 인코딩할 때 성능문제가 발생했기 때문이다. 약 6프레임 정도 밖에 나오지 않는다.. 그래서 대체할 코덱을 찾느라고 작업했다.
0. FFmpeg 0.8.2 버전을 가지고 테스트하였고, 예제는 ffmpeg-0.8.2/doc/example/encoding_example.c 파일을 사용하였다.
1. FFmpeg을 가지고 MPEG4 Video 영상을 인코딩 하기 위해 사용한 옵션은 아래와 같다.
249 /* put sample parameters */
255 c->bit_rate = 300 * 1000;
257 /* resolution must be a multiple of two */
258 c->width = 352;
259 c->height = 288;
260 /* frames per second */
261 c->time_base= (AVRational){1,25};
262 c->gop_size = 25; /* emit one intra frame every ten frames */
263 c->pix_fmt = PIX_FMT_YUV420P;
2. H.264와 달리 PTS 값을 매번 설정하지 않고 아래와 같이 설정하면 경고나 오류없이 동작한다.
221 AVFrame *picture;
326 picture->pts = AV_NOPTS_VALUE;
3. 그러나 문제는... CBR 비트레이트 컨트롤이 제대로 안되는 문제가 발생하였다.
구글링과 삽질을 통하여 옵션을 찾았다. bufsize와 maxrate 옵션을 설정하니 CBR 비트레이트 설정이 가능하였다. (bufsize maxrate 옵션이 무것인지는 인터넷 찾아보면 어렵지 않게 찾을 수 있다.) 이 설정은 영상을 네트워크로 전송할 때와 같은 경우에 쓰면 된다.
ffmpeg 바이너리를 가지고 아래와 같이 설정하면 된다.
$ ffmpeg -i example.y4m -vcodec mpeg4 -bufsize 300K -b 300K -maxrate 300K video_300k.mp4
4. 테스트 코드에 적용시켜 보았다.
249 /* put sample parameters */
250 c->rc_max_rate = 300 * 1000;
251 c->bit_rate = c->rc_max_rate >> 1;
252 c->rc_buffer_size = c->rc_max_rate;
254 /* resolution must be a multiple of two */
255 c->width = 352;
256 c->height = 288;
257 /* frames per second */
258 c->time_base= (AVRational){1,25};
259 c->gop_size = 25; /* emit one intra frame every ten frames */
260 c->pix_fmt = PIX_FMT_YUV420P;
테스트 결과 동작은 하는데.... 아래와 같은
[mpeg4 @ 0x90ba020] rc buffer underflow
메시지가 발생한다... 내가 뭔가 빠뜨린것 같은데... 설정이 부족한거 같다.
구글링했으나 못찾았다..
그래서 코드를 뒤졌다..
$ grep -R "rc buffer underflow" ../../*
../../libavcodec/ratecontrol.c: av_log(s->avctx, AV_LOG_ERROR, "rc buffer underflow\n");
뭔가 있다..
$ vi ../../libavcodec/ratecontrol.c
266 int ff_vbv_update(MpegEncContext *s, int frame_size){
267 RateControlContext *rcc= &s->rc_context;
268 const double fps= 1/av_q2d(s->avctx->time_base);
269 const int buffer_size= s->avctx->rc_buffer_size;
270 const double min_rate= s->avctx->rc_min_rate/fps;
271 const double max_rate= s->avctx->rc_max_rate/fps;
272
273 //printf("%d %f %d %f %f\n", buffer_size, rcc->buffer_index, frame_size, min_rate, max_rate);
274 av_log(s->avctx, AV_LOG_ERROR, "%d %f %d %f %f\n", buffer_size, rcc->buffer_index, frame_size, min_rate, max_rate);
275 if(buffer_size){
276 int left;
277
278 rcc->buffer_index-= frame_size;
279 if(rcc->buffer_index < 0){
280 av_log(s->avctx, AV_LOG_ERROR, "rc buffer underflow\n");
281 rcc->buffer_index= 0;
282 }
279 라인에서 rcc->buffer_index 값 때문에 메시지를 찍네..
buffer_index 값으로 검색 또 해봤다..
66 int ff_rate_control_init(MpegEncContext *s)
.
.
.
127 rcc->buffer_index= s->avctx->rc_initial_buffer_occupancy;
127 라인에서 avctx->rc_initial_buffer_occupancy 값을 설정하네.. 빙고!!!
구글링 해보니 rc_max_rate값과 동일하게 설정을 하더라...
그래서 아래와 같이 설정을 했다.
249 /* put sample parameters */
250 c->rc_max_rate = 300 * 1000;
251 c->bit_rate = c->rc_max_rate >> 1;
252 c->rc_buffer_size = c->rc_max_rate;
253 c->rc_initial_buffer_occupancy = c->rc_max_rate;
254 /* resolution must be a multiple of two */
255 c->width = 352;
256 c->height = 288;
257 /* frames per second */
258 c->time_base= (AVRational){1,25};
259 c->gop_size = 25; /* emit one intra frame every ten frames */
260 c->pix_fmt = PIX_FMT_YUV420P;
아래 경고 문구가 사라짐..ㅋㅋ 행복하구나..
[mpeg4 @ 0x90ba020] rc buffer underflow
이렇게 쓰면 될 듯... 이상!!
위 코드를 보면 알겠지만 비트레이트 설정한데로 정확하게 나오지는 않는다.
rc_max_rate와 bit_rate 항목을 알맞게 설정해서 써야한다.
테스트 코드 아래 첨부..
* 성능 테스트 결과
- 비트레이트가 낮을 수록 성능이 떨어지는 것 같음.
- rc_initial_buffer_occupancy 값을 어떻게 설정하느냐에 따라 비트레이트가 달라지는 것 같음.
- [mpeg4 @ 0x8d60020] impossible bitrate constraints, this will fail 이런 메시지가 발생함.
비트레이트와 최대 비트레이트를 같게 하면 나타남..
- 테스트 중 낮은 비트레이트를 설정하면 [mpeg4 @ 0x90ba020] rc buffer underflow]
메시지가 동일하게 발생함. 비트레이트를 터무니 없게 낮게 설정할 경우 발생하는 것으로 판단됨. CIF 영상에 비트레이트를 100K 로 설정하면 발생하나 QCIF에 비트레이트 100K로 설정하면 정상적으로 영상이 출력됨.
- 비트레이트를 맞추기 위해서 해상도, 프레임레이트 별로 설정하는 rc_max_rate, rc_buffer_size, rc_initial_buffer_occupancy 값을 테스트하여 표로 만들어서 정리해야 할 것으로 생각됨.
249 /* put sample parameters */
250 c->rc_max_rate = 300 * 1000;
251 c->bit_rate = c->rc_max_rate >> 1;
252 c->rc_buffer_size = c->rc_max_rate;
253 c->rc_initial_buffer_occupancy = c->rc_max_rate;
여기에는 테스트한 발자취를 남긴다. 따라서 삽질하는 과정도 포함되어 있다.
이 작업을 한 이유는 이전에 작업한 libx264 라이브러리가 안드로이드 플랫폼에서 영상을 인코딩할 때 성능문제가 발생했기 때문이다. 약 6프레임 정도 밖에 나오지 않는다.. 그래서 대체할 코덱을 찾느라고 작업했다.
0. FFmpeg 0.8.2 버전을 가지고 테스트하였고, 예제는 ffmpeg-0.8.2/doc/example/encoding_example.c 파일을 사용하였다.
1. FFmpeg을 가지고 MPEG4 Video 영상을 인코딩 하기 위해 사용한 옵션은 아래와 같다.
249 /* put sample parameters */
255 c->bit_rate = 300 * 1000;
257 /* resolution must be a multiple of two */
258 c->width = 352;
259 c->height = 288;
260 /* frames per second */
261 c->time_base= (AVRational){1,25};
262 c->gop_size = 25; /* emit one intra frame every ten frames */
263 c->pix_fmt = PIX_FMT_YUV420P;
2. H.264와 달리 PTS 값을 매번 설정하지 않고 아래와 같이 설정하면 경고나 오류없이 동작한다.
221 AVFrame *picture;
326 picture->pts = AV_NOPTS_VALUE;
3. 그러나 문제는... CBR 비트레이트 컨트롤이 제대로 안되는 문제가 발생하였다.
구글링과 삽질을 통하여 옵션을 찾았다. bufsize와 maxrate 옵션을 설정하니 CBR 비트레이트 설정이 가능하였다. (bufsize maxrate 옵션이 무것인지는 인터넷 찾아보면 어렵지 않게 찾을 수 있다.) 이 설정은 영상을 네트워크로 전송할 때와 같은 경우에 쓰면 된다.
ffmpeg 바이너리를 가지고 아래와 같이 설정하면 된다.
$ ffmpeg -i example.y4m -vcodec mpeg4 -bufsize 300K -b 300K -maxrate 300K video_300k.mp4
4. 테스트 코드에 적용시켜 보았다.
249 /* put sample parameters */
250 c->rc_max_rate = 300 * 1000;
251 c->bit_rate = c->rc_max_rate >> 1;
252 c->rc_buffer_size = c->rc_max_rate;
254 /* resolution must be a multiple of two */
255 c->width = 352;
256 c->height = 288;
257 /* frames per second */
258 c->time_base= (AVRational){1,25};
259 c->gop_size = 25; /* emit one intra frame every ten frames */
260 c->pix_fmt = PIX_FMT_YUV420P;
테스트 결과 동작은 하는데.... 아래와 같은
[mpeg4 @ 0x90ba020] rc buffer underflow
메시지가 발생한다... 내가 뭔가 빠뜨린것 같은데... 설정이 부족한거 같다.
구글링했으나 못찾았다..
그래서 코드를 뒤졌다..
$ grep -R "rc buffer underflow" ../../*
../../libavcodec/ratecontrol.c: av_log(s->avctx, AV_LOG_ERROR, "rc buffer underflow\n");
뭔가 있다..
$ vi ../../libavcodec/ratecontrol.c
266 int ff_vbv_update(MpegEncContext *s, int frame_size){
267 RateControlContext *rcc= &s->rc_context;
268 const double fps= 1/av_q2d(s->avctx->time_base);
269 const int buffer_size= s->avctx->rc_buffer_size;
270 const double min_rate= s->avctx->rc_min_rate/fps;
271 const double max_rate= s->avctx->rc_max_rate/fps;
272
273 //printf("%d %f %d %f %f\n", buffer_size, rcc->buffer_index, frame_size, min_rate, max_rate);
274 av_log(s->avctx, AV_LOG_ERROR, "%d %f %d %f %f\n", buffer_size, rcc->buffer_index, frame_size, min_rate, max_rate);
275 if(buffer_size){
276 int left;
277
278 rcc->buffer_index-= frame_size;
279 if(rcc->buffer_index < 0){
280 av_log(s->avctx, AV_LOG_ERROR, "rc buffer underflow\n");
281 rcc->buffer_index= 0;
282 }
279 라인에서 rcc->buffer_index 값 때문에 메시지를 찍네..
buffer_index 값으로 검색 또 해봤다..
66 int ff_rate_control_init(MpegEncContext *s)
.
.
.
127 rcc->buffer_index= s->avctx->rc_initial_buffer_occupancy;
127 라인에서 avctx->rc_initial_buffer_occupancy 값을 설정하네.. 빙고!!!
구글링 해보니 rc_max_rate값과 동일하게 설정을 하더라...
그래서 아래와 같이 설정을 했다.
249 /* put sample parameters */
250 c->rc_max_rate = 300 * 1000;
251 c->bit_rate = c->rc_max_rate >> 1;
252 c->rc_buffer_size = c->rc_max_rate;
253 c->rc_initial_buffer_occupancy = c->rc_max_rate;
254 /* resolution must be a multiple of two */
255 c->width = 352;
256 c->height = 288;
257 /* frames per second */
258 c->time_base= (AVRational){1,25};
259 c->gop_size = 25; /* emit one intra frame every ten frames */
260 c->pix_fmt = PIX_FMT_YUV420P;
아래 경고 문구가 사라짐..ㅋㅋ 행복하구나..
[mpeg4 @ 0x90ba020] rc buffer underflow
이렇게 쓰면 될 듯... 이상!!
위 코드를 보면 알겠지만 비트레이트 설정한데로 정확하게 나오지는 않는다.
rc_max_rate와 bit_rate 항목을 알맞게 설정해서 써야한다.
테스트 코드 아래 첨부..
* 성능 테스트 결과
- 비트레이트가 낮을 수록 성능이 떨어지는 것 같음.
- rc_initial_buffer_occupancy 값을 어떻게 설정하느냐에 따라 비트레이트가 달라지는 것 같음.
- [mpeg4 @ 0x8d60020] impossible bitrate constraints, this will fail 이런 메시지가 발생함.
비트레이트와 최대 비트레이트를 같게 하면 나타남..
- 테스트 중 낮은 비트레이트를 설정하면 [mpeg4 @ 0x90ba020] rc buffer underflow]
메시지가 동일하게 발생함. 비트레이트를 터무니 없게 낮게 설정할 경우 발생하는 것으로 판단됨. CIF 영상에 비트레이트를 100K 로 설정하면 발생하나 QCIF에 비트레이트 100K로 설정하면 정상적으로 영상이 출력됨.
- 비트레이트를 맞추기 위해서 해상도, 프레임레이트 별로 설정하는 rc_max_rate, rc_buffer_size, rc_initial_buffer_occupancy 값을 테스트하여 표로 만들어서 정리해야 할 것으로 생각됨.
249 /* put sample parameters */
250 c->rc_max_rate = 300 * 1000;
251 c->bit_rate = c->rc_max_rate >> 1;
252 c->rc_buffer_size = c->rc_max_rate;
253 c->rc_initial_buffer_occupancy = c->rc_max_rate;
FFmpeg에 x264 인코더 사용방법
출처 : http://iamlow.tistory.com/entry/FFmpeg%EC%97%90-x264-%EC%9D%B8%EC%BD%94%EB%8D%94-%EC%82%AC%EC%9A%A9%EB%B0%A9%EB%B2%95
1. FFmpeg을 통하여 x264를 사용하고자 하였다.
용도는 카메라 영상을 H.264 로 인코딩하여 실시간으로 전송하는데 사용하려고 한다.
이에 알맞는 x264 코덱의 환경 설정 방법들 중 중요한 부분을 아래 적는다.
- Baseline Profile을 사용(B Frame 사용안함)
* x264는 Constrained baseline 만 지원하고 Baseline Profile는 지원 안한댄다..
그래서 Constrained baseline을 사용하기로 했다. ffmpeg에서 baseline으로 설정하면 자동으로 Constrained baseline으로 설정된다.
- Level 1.3을 사용
- RC(Rate Control): ABR(Average Bit Rate)
* Baseline Profile/Level 1.3 등의 정보는 H.264 로 검색하면 쉽게 찾을 수 있다.
* RC와 관련된 사항은 x264로 검색하면 어렵지 않게 찾을 수 있다.
--> 참고 사이트: http://yg05123.blog.me/70042737774
2. x264 코덱은 설정항목이 엄청 많다.. 30개는 넘는 거 같다.
--> 참고사이트
111 /**
112 * @remark reference sites for x264 setting
113 * http://vidcorea.net/lecture/2156
114 * http://avidemux.org/admWiki/doku.php?id=tutorial:h.264
115 * http://vidcorea.net/2146
116 * http://sites.google.com/site/linuxencoding/x264-ffmpeg-mapping
117 * http://mewiki.project357.com/wiki/X264_Settings
118 */
게다가 인터넷을 검색해보면 ffmpeg 실행파일에 command arguement를 사용하여 영상을 인코딩 하는 코드는 쉽게 찾을 수 있다.
그러나 ffmpeg API를 사용하여 코드 상에서 설정하는 방법이 있으나 대부분 미흡한 부분이 많았다. (내가 못 찾았을 확률이 크다.)
그래서 ffmpeg.c 파일을 분석했다.. 함수포인터에다가.. command arguement 파싱하는 부분들이 많아서 코드보기 무지하게 난해했다.
가장 문제가 되었던 부분은 2 부분이다.
1) profile 설정 ==> 설정하는 방법을 인터넷에서 못찾았다.
2) bitrate 설정 ==> 설정하는 부분을 찾았으나 실제 테스트 해보니 정상동작 안했다.
이 두 부분은 4번 항목에서 설명하고 3번항목에서 x264 간단한 설정 방법을 아래서 설명한다.
3. ffmpeg에서 x264 영상설정하기
- ffmpeg 0.8.2 버전을 사용하였다.
- 테스트 코드는 ffmpeg 소스를 받아보면 doc/example 디렉토리에 encoding_example.c 파일을 수정하면서 테스트 했다. (여기 예제로만 x264 영상설정.... 택도없다...)
- 일단 H.264 코드를 찾는다.
codec = avcodec_find_encoder(CODEC_ID_H264);
- 찾은 후 AVCodecContext 구조체에 영상 설정을 해야 한다.
AVCodecContext *c = avcodec_alloc_context();
이 구조체에 영상설정과 관련된 항목이 모여있다. x264 뿐만 아니라 다른 코덱도 동일하게 이 구조체를 사용한다.( 공통적으로 사용하려다 보니.. 변수명들이 x264에 어느 변수들이랑 매핑되는지 찾기가 좀 힘들다. libavcodec/libx264.c 파일에 X264_init함수보면 대충 알 수 있다.)
- AVCodecContext 구조체에는 엄청나게 많은 필드가 있으나, 실제 사용을 위해 설정할 필드는 몇 개 안된다. 내가 사용한 필드 들은 아래와 같다.
coder_type ==> CAVLC or CABAC 엔트로피 모드를 설정한다.(참고로 baseline profile은 CAVLC만 지원한다.)
gop_size ==> group of picture 이다. 자세한건 인터넷 검색...
bitrate ==> 말그대로 bitrate
qmin ==> quality min~~ 영상화질의 범위의 최소값을 지정한다.
qmax ==> quality max ~~ 영상화질의 범위의 최대값을 지정한다.
max_qdiff ==> quality 값이 변화량을 지정한다. 즉 여기에 정해진 값 단위로 증가되거나 감소된다는 뜻이다. 예를 들어 현재 q값이 10이면 14, 18이런식으로 증가되거나 감소된다는 말이다.
pix_fmt ==> pixel format을 말한다.. RGB, YUV 이런거 말이다.
width, height ==> 해상도다..
time_base.num ==> 프레임레이트 설정할 때 쓰는데 그냥 1쓰면된다.
time_base.den ==> 프레임레이트 넣으면 된다. 25프레임이면 25 넣으면 된다.
내가 코드에 설정한 값들은 아래와 같다.
200 c->coder_type = FF_CODER_TYPE_VLC;
201 // c->refs = 3;
202 c->flags |= CODEC_FLAG_LOOP_FILTER;
203 c->deblockalpha = 0;
204 c->deblockbeta = 0;
205 c->partitions = X264_PART_I4X4
206 | X264_PART_P8X8
207 | X264_PART_B8X8;
208 // c->me_method = ME_HEX;
209 // c->me_subpel_quality = 7;
210 // c->flags2 |= CODEC_FLAG2_PSY;
211 // c->psy_rd = 1.0;
212 // c->psy_trellis = 0.0;
213 // c->flags2 |= CODEC_FLAG2_MIXED_REFS;
214 // c->me_range = 16;
215 // c->me_cmp = FF_CMP_CHROMA;
216 // c->trellis = 0; // 0: speed up!
217 // c->flags2 &= ~CODEC_FLAG2_8X8DCT;
218 // c->flags2 |= CODEC_FLAG2_FASTPSKIP;
219 // c->chromaoffset = -2;
220 // c->thread_count = 1;
221 // c->slices = 0;
222 // c->noise_reduction = 0;
223 // c->flags |= CODEC_FLAG_INTERLACED_DCT;
224 // c->max_b_frames = 0;
225 // c->weighted_p_pred = 0;
226 c->gop_size = 25;
227 // c->keyint_min = 25;
228 // c->scenechange_threshold = 40;
229 // c->flags2 &= ~CODEC_FLAG2_INTRA_REFRESH;
230 // c->rc_lookahead = 40;
231 // c->crf = 23.0; // ABR
232 // c->cqp = -1; // ABR
233 // c->flags2 |= CODEC_FLAG2_MBTREE;
234 c->bit_rate = 10 * 1000 * 1000;
235 // c->bit_rate_tolerance = 1.0; //not config
236 // c->qcompress = 0.6;
237 c->qmin = 10;
238 c->qmax = 51;
239 c->max_qdiff = 4;
240 // c->i_quant_factor = 10/14; // i_qfactor=0.71
241 // c->aq_mode = 1;
242 // c->aq_strength = 1.00;
243
244 // c->rc_max_rate = 200 * 1000;
245 // c->rc_min_rate = 300 * 1000;
246 // c->rc_buffer_size = c->rc_max_rate * 100;
247 // c->flags |= CODEC_FLAG_GLOBAL_HEADER;
248 // c->flags |= CODEC_FLAG_PASS1;
249
250 /* */
251 c->pix_fmt = PIX_FMT_YUV420P;
252 c->width = 384; // 320; //176;
253 c->height = 288; //240; // 144;
254 c->time_base.num = 1;
255 c->time_base.den = 25; //15;
이렇게만 설정하고 예제 프로그램을 돌렸다.
out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
테스트 프로그램은 동작은 하는데 인코딩 되어 나오는 데이터가 0바이트라고 나온다.
뭐지?? 이런..
근데 인코딩 함수를 호출하는 루프문이 있는데.. 루프문을 더 오래 돌려보니까 인코딩된 데이터가 나온다. 예제 소스를 자세히 보면 알겠지만. 인코더에 YUV영상을 넣으면 인코딩된 영상이 바로 나오는 것이 아니라 나중에 호출한 함수에서 이전에 입력했던 YUV영상이 나온다. 그래서 예제 소스를 자세히 보면 아래와 같은 부분이 있다.
923 /* get the delayed frames */
924 for(out_size = 1; out_size; i++) {
925 fflush(stdout);
926
927 out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);
928 printf("write frame %3d (size=%5d)\n", i, out_size);
929 fwrite(outbuf, 1, out_size, f);
930 total_size += out_size;
931 }
932
이 부분이 딜레이 된 인코딩 영상이 나오는 것을 처리한다.
일단 영상은 나온다. 그런데...
문제점이 있는게.. 난 baseline profile을 서야하는데 x264가 계속 Main Profile로 설정되는 것이다.
그리고 비트레이트 컨트롤이 안된다. 아까 앞서 말한 2 가지 문제점이다.
4. 두가지 문제점을 나누어 설명한다.
1) Baseline Profile 설정하기
- 일단 설정하는 코드는 아래와 같다.
306 c->priv_data = alloc_priv_context(codec->priv_data_size, codec->priv_class);
307 int flags = AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM;
308 if (av_find_opt(c->priv_data, "profile", NULL, flags, flags)) {
309 if (av_set_string3(c->priv_data, "profile", "baseline", 1, NULL) < 0) {
310 fprintf(stderr, "Invalid value '%s' for option '%s'\n",
311 "profile", "baseline");
312 exit(1);
313 }
314 }
- 이 코드를 cmdutils.c 에서 찾았다. 인터넷 아무리 뒤져도 이렇게 쓰라는 설명 없다..ㅠㅠ
- 알고나니 별거 없다.
- 309번 라인 처럼 문자열을 설정하면 x264 라이브러리에 설정된다.
- 원하는 프로파일을 그냥 문자열로 쓰면 설정할 수 있다.
2) Bitrate 설정하기
- 프로그램을 실행하면 아래와 같은 경고 메시지가 뜬다.
[libx264 @ 0x8455020] non-strictly-monotonic PTS
- 이것을 설정하는 방법은 인터넷에 나와 있다.
==> http://lists.libav.org/pipermail/libav-user/2011-February/005995.html
- 근데 이대로 하면 안된다. 다른 곳 찾아봐도 안나온다.
- 그래서 정상동작하는 ffmpeg 라이브러리에 이 값을 어떻게 쓰는지 로그를 찍어보았다. 근데.. 허무하다.. 그냥 1씩 증가 시켜써 썼다.. 그래서 나도 picture->pts = i++; 이렇게 쓰니.. bitrate 제어가 된다. 허무하다..
위 사항을 모두 반영하니 영상 설정도 된다.
단 위 사항들은 경험적으로 얻은 방법이기에 올바른 사용법이 아닐 확률이 높다.
참고만 합시다..!!
* 첨부파일로 내가 사용한 지저분한 테스트 프로그램을 올린다.
나중에 정리가 되면 좀 더 깨끗한 코드를 올릴 수도 있겠지만..
보는데 별 무리 없을 듯..
5. 이건 테스트 시 참고하세요.
- ffmpeg 프로그램이나 x264 프로그램을 을 실행하여 인코딩 할 때 보면 예제로 사용하는 영상 타입이 y4m이라는 확장자를 사용하는데, 이 예제 영상이 필요하시면 여기서 다운받아 쓰세요.
예제 사이트: http://samples.mplayerhq.hu/yuv4mpeg2/
- ffmpeg API를 통하여 설정한 항목이 x264 라이브러리에 정상적으로 설정이 되는지를 확인하고 싶을 때 아래처럼 추가해서 테스트 하세요.
(AVCodecContext *)c->flags |= CODEC_FLAG_GLOBAL_HEADER;
그러면 libx264에서 설정된 옵션을 화면에 텍스트로 뿌려 줍니다.
[libx264 @ 0x974f020] 264 - core 116 r2057 0ba8a9c - H.264/MPEG-4 AVC codec - Copyleft 2003-2011 - http://www.videolan.org/x264.html - options: cabac=0 ref=1 deblock=1:0:0 analyse=0x1:0x111 me=dia subme=8 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=4 chroma_me=0 trellis=0 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 keyint=25 keyint_min=13 scenecut=0 intra_refresh=0 rc_lookahead=25 rc=abr mbtree=1 bitrate=10000 ratetol=1.0 qcomp=0.50 qpmin=10 qpmax=51 qpstep=4 ip_ratio=1.25 aq=1:1.00
H.264 영상은 SPS, PPS 정보를 가지고 있는데, 이 정보는 avcodec_encode_video() 함수를 맨 처음 호출할 때 인코딩된 영상데이터 제일 앞에 포함되어 있다.
그러나 SDP를 사용하거나 기타 등등 의 경우 SPS, PPS 정보를 따로 추출하여 사용해야 할 경우가 있다. 이럴 때 CODEC_FLAG_GLOBAL_HEADER 옵션을 사용하면 된다.
이 옵션을 설정한 다음에 avcodec_encode_video() 함수를 호출하면 SPS, PPS 정보가 들어있지 않게 된다. 따라서 아래 방법을 통하여 SPS, PPS 정보를 얻어야 한다.
206 /* open codec */
207 ret = avcodec_open(f->ctx, codec);
208 assert(!ret, "avcodec_open is failed!");
209
210 /* get sps, pps */
211 #if 0
212 trace_sprop(f->ctx);
213 #endif
214 f->extradata_size = f->ctx->extradata_size;
215 memcpy(f->extradata, f->ctx->extradata, f->ctx->extradata_size);
AVCodecContext 구조체 안에 extradata_size에는 SPS, PPS 크기정보가 들어있고, 실제 데이터는 extradata에 들어있다. 이 값은 avcodec_open() 호출한 후에 얻을 수 있다.
6. x264 라이브러리는 기본설정으로 SPS, PPS가 주기적으로 나온다.. 참고하시길....
주기적으로 나오는 것을 설정하는 방법은 모름.
7. x264에 보면 아래와 같은 SEI 정보를 생성하여 인코딩된 영상에 들어가게 된다.
264 - core 116 r2057 0ba8a9c - H.264/MPEG-4 AVC codec - Copyleft 2003-2011 -http://www.videolan.org/x264.html - options: cabac=0 ref=1 deblock=1:0:0 analyse=0x1:0x111 me=dia subme=8 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=4 chroma_me=0 trellis=0 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 keyint=25 keyint_min=13 scenecut=0 intra_refresh=0 rc_lookahead=25 rc=abr mbtree=1 bitrate=10000 ratetol=1.0 qcomp=0.50 qpmin=10 qpmax=51 qpstep=4 ip_ratio=1.25 aq=1:1.00
avctx->extradata = av_malloc(s);
avctx->extradata_size = encode_nals(avctx, avctx->extradata, s, nal, nnal, 1);
마지막 인자의 값을 1 을 설정하면 avcodec_encode_video() 함수 호출 시에 SEI 정보가 나오고, 0으로 설정하면, extradata안에 SEI 정보가 들어있게 된다.
1. FFmpeg을 통하여 x264를 사용하고자 하였다.
용도는 카메라 영상을 H.264 로 인코딩하여 실시간으로 전송하는데 사용하려고 한다.
이에 알맞는 x264 코덱의 환경 설정 방법들 중 중요한 부분을 아래 적는다.
- Baseline Profile을 사용(B Frame 사용안함)
* x264는 Constrained baseline 만 지원하고 Baseline Profile는 지원 안한댄다..
그래서 Constrained baseline을 사용하기로 했다. ffmpeg에서 baseline으로 설정하면 자동으로 Constrained baseline으로 설정된다.
- Level 1.3을 사용
- RC(Rate Control): ABR(Average Bit Rate)
* Baseline Profile/Level 1.3 등의 정보는 H.264 로 검색하면 쉽게 찾을 수 있다.
* RC와 관련된 사항은 x264로 검색하면 어렵지 않게 찾을 수 있다.
--> 참고 사이트: http://yg05123.blog.me/70042737774
2. x264 코덱은 설정항목이 엄청 많다.. 30개는 넘는 거 같다.
--> 참고사이트
111 /**
112 * @remark reference sites for x264 setting
113 * http://vidcorea.net/lecture/2156
114 * http://avidemux.org/admWiki/doku.php?id=tutorial:h.264
115 * http://vidcorea.net/2146
116 * http://sites.google.com/site/linuxencoding/x264-ffmpeg-mapping
117 * http://mewiki.project357.com/wiki/X264_Settings
118 */
게다가 인터넷을 검색해보면 ffmpeg 실행파일에 command arguement를 사용하여 영상을 인코딩 하는 코드는 쉽게 찾을 수 있다.
그러나 ffmpeg API를 사용하여 코드 상에서 설정하는 방법이 있으나 대부분 미흡한 부분이 많았다. (내가 못 찾았을 확률이 크다.)
그래서 ffmpeg.c 파일을 분석했다.. 함수포인터에다가.. command arguement 파싱하는 부분들이 많아서 코드보기 무지하게 난해했다.
가장 문제가 되었던 부분은 2 부분이다.
1) profile 설정 ==> 설정하는 방법을 인터넷에서 못찾았다.
2) bitrate 설정 ==> 설정하는 부분을 찾았으나 실제 테스트 해보니 정상동작 안했다.
이 두 부분은 4번 항목에서 설명하고 3번항목에서 x264 간단한 설정 방법을 아래서 설명한다.
3. ffmpeg에서 x264 영상설정하기
- ffmpeg 0.8.2 버전을 사용하였다.
- 테스트 코드는 ffmpeg 소스를 받아보면 doc/example 디렉토리에 encoding_example.c 파일을 수정하면서 테스트 했다. (여기 예제로만 x264 영상설정.... 택도없다...)
- 일단 H.264 코드를 찾는다.
codec = avcodec_find_encoder(CODEC_ID_H264);
- 찾은 후 AVCodecContext 구조체에 영상 설정을 해야 한다.
AVCodecContext *c = avcodec_alloc_context();
이 구조체에 영상설정과 관련된 항목이 모여있다. x264 뿐만 아니라 다른 코덱도 동일하게 이 구조체를 사용한다.( 공통적으로 사용하려다 보니.. 변수명들이 x264에 어느 변수들이랑 매핑되는지 찾기가 좀 힘들다. libavcodec/libx264.c 파일에 X264_init함수보면 대충 알 수 있다.)
- AVCodecContext 구조체에는 엄청나게 많은 필드가 있으나, 실제 사용을 위해 설정할 필드는 몇 개 안된다. 내가 사용한 필드 들은 아래와 같다.
coder_type ==> CAVLC or CABAC 엔트로피 모드를 설정한다.(참고로 baseline profile은 CAVLC만 지원한다.)
gop_size ==> group of picture 이다. 자세한건 인터넷 검색...
bitrate ==> 말그대로 bitrate
qmin ==> quality min~~ 영상화질의 범위의 최소값을 지정한다.
qmax ==> quality max ~~ 영상화질의 범위의 최대값을 지정한다.
max_qdiff ==> quality 값이 변화량을 지정한다. 즉 여기에 정해진 값 단위로 증가되거나 감소된다는 뜻이다. 예를 들어 현재 q값이 10이면 14, 18이런식으로 증가되거나 감소된다는 말이다.
pix_fmt ==> pixel format을 말한다.. RGB, YUV 이런거 말이다.
width, height ==> 해상도다..
time_base.num ==> 프레임레이트 설정할 때 쓰는데 그냥 1쓰면된다.
time_base.den ==> 프레임레이트 넣으면 된다. 25프레임이면 25 넣으면 된다.
내가 코드에 설정한 값들은 아래와 같다.
200 c->coder_type = FF_CODER_TYPE_VLC;
201 // c->refs = 3;
202 c->flags |= CODEC_FLAG_LOOP_FILTER;
203 c->deblockalpha = 0;
204 c->deblockbeta = 0;
205 c->partitions = X264_PART_I4X4
206 | X264_PART_P8X8
207 | X264_PART_B8X8;
208 // c->me_method = ME_HEX;
209 // c->me_subpel_quality = 7;
210 // c->flags2 |= CODEC_FLAG2_PSY;
211 // c->psy_rd = 1.0;
212 // c->psy_trellis = 0.0;
213 // c->flags2 |= CODEC_FLAG2_MIXED_REFS;
214 // c->me_range = 16;
215 // c->me_cmp = FF_CMP_CHROMA;
216 // c->trellis = 0; // 0: speed up!
217 // c->flags2 &= ~CODEC_FLAG2_8X8DCT;
218 // c->flags2 |= CODEC_FLAG2_FASTPSKIP;
219 // c->chromaoffset = -2;
220 // c->thread_count = 1;
221 // c->slices = 0;
222 // c->noise_reduction = 0;
223 // c->flags |= CODEC_FLAG_INTERLACED_DCT;
224 // c->max_b_frames = 0;
225 // c->weighted_p_pred = 0;
226 c->gop_size = 25;
227 // c->keyint_min = 25;
228 // c->scenechange_threshold = 40;
229 // c->flags2 &= ~CODEC_FLAG2_INTRA_REFRESH;
230 // c->rc_lookahead = 40;
231 // c->crf = 23.0; // ABR
232 // c->cqp = -1; // ABR
233 // c->flags2 |= CODEC_FLAG2_MBTREE;
234 c->bit_rate = 10 * 1000 * 1000;
235 // c->bit_rate_tolerance = 1.0; //not config
236 // c->qcompress = 0.6;
237 c->qmin = 10;
238 c->qmax = 51;
239 c->max_qdiff = 4;
240 // c->i_quant_factor = 10/14; // i_qfactor=0.71
241 // c->aq_mode = 1;
242 // c->aq_strength = 1.00;
243
244 // c->rc_max_rate = 200 * 1000;
245 // c->rc_min_rate = 300 * 1000;
246 // c->rc_buffer_size = c->rc_max_rate * 100;
247 // c->flags |= CODEC_FLAG_GLOBAL_HEADER;
248 // c->flags |= CODEC_FLAG_PASS1;
249
250 /* */
251 c->pix_fmt = PIX_FMT_YUV420P;
252 c->width = 384; // 320; //176;
253 c->height = 288; //240; // 144;
254 c->time_base.num = 1;
255 c->time_base.den = 25; //15;
이렇게만 설정하고 예제 프로그램을 돌렸다.
out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
테스트 프로그램은 동작은 하는데 인코딩 되어 나오는 데이터가 0바이트라고 나온다.
뭐지?? 이런..
근데 인코딩 함수를 호출하는 루프문이 있는데.. 루프문을 더 오래 돌려보니까 인코딩된 데이터가 나온다. 예제 소스를 자세히 보면 알겠지만. 인코더에 YUV영상을 넣으면 인코딩된 영상이 바로 나오는 것이 아니라 나중에 호출한 함수에서 이전에 입력했던 YUV영상이 나온다. 그래서 예제 소스를 자세히 보면 아래와 같은 부분이 있다.
923 /* get the delayed frames */
924 for(out_size = 1; out_size; i++) {
925 fflush(stdout);
926
927 out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);
928 printf("write frame %3d (size=%5d)\n", i, out_size);
929 fwrite(outbuf, 1, out_size, f);
930 total_size += out_size;
931 }
932
이 부분이 딜레이 된 인코딩 영상이 나오는 것을 처리한다.
일단 영상은 나온다. 그런데...
문제점이 있는게.. 난 baseline profile을 서야하는데 x264가 계속 Main Profile로 설정되는 것이다.
그리고 비트레이트 컨트롤이 안된다. 아까 앞서 말한 2 가지 문제점이다.
4. 두가지 문제점을 나누어 설명한다.
1) Baseline Profile 설정하기
- 일단 설정하는 코드는 아래와 같다.
306 c->priv_data = alloc_priv_context(codec->priv_data_size, codec->priv_class);
307 int flags = AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM;
308 if (av_find_opt(c->priv_data, "profile", NULL, flags, flags)) {
309 if (av_set_string3(c->priv_data, "profile", "baseline", 1, NULL) < 0) {
310 fprintf(stderr, "Invalid value '%s' for option '%s'\n",
311 "profile", "baseline");
312 exit(1);
313 }
314 }
- 이 코드를 cmdutils.c 에서 찾았다. 인터넷 아무리 뒤져도 이렇게 쓰라는 설명 없다..ㅠㅠ
- 알고나니 별거 없다.
- 309번 라인 처럼 문자열을 설정하면 x264 라이브러리에 설정된다.
- 원하는 프로파일을 그냥 문자열로 쓰면 설정할 수 있다.
2) Bitrate 설정하기
- 프로그램을 실행하면 아래와 같은 경고 메시지가 뜬다.
[libx264 @ 0x8455020] non-strictly-monotonic PTS
- 이것을 설정하는 방법은 인터넷에 나와 있다.
==> http://lists.libav.org/pipermail/libav-user/2011-February/005995.html
- 근데 이대로 하면 안된다. 다른 곳 찾아봐도 안나온다.
- 그래서 정상동작하는 ffmpeg 라이브러리에 이 값을 어떻게 쓰는지 로그를 찍어보았다. 근데.. 허무하다.. 그냥 1씩 증가 시켜써 썼다.. 그래서 나도 picture->pts = i++; 이렇게 쓰니.. bitrate 제어가 된다. 허무하다..
위 사항을 모두 반영하니 영상 설정도 된다.
단 위 사항들은 경험적으로 얻은 방법이기에 올바른 사용법이 아닐 확률이 높다.
참고만 합시다..!!
* 첨부파일로 내가 사용한 지저분한 테스트 프로그램을 올린다.
나중에 정리가 되면 좀 더 깨끗한 코드를 올릴 수도 있겠지만..
보는데 별 무리 없을 듯..
5. 이건 테스트 시 참고하세요.
- ffmpeg 프로그램이나 x264 프로그램을 을 실행하여 인코딩 할 때 보면 예제로 사용하는 영상 타입이 y4m이라는 확장자를 사용하는데, 이 예제 영상이 필요하시면 여기서 다운받아 쓰세요.
예제 사이트: http://samples.mplayerhq.hu/yuv4mpeg2/
- ffmpeg API를 통하여 설정한 항목이 x264 라이브러리에 정상적으로 설정이 되는지를 확인하고 싶을 때 아래처럼 추가해서 테스트 하세요.
(AVCodecContext *)c->flags |= CODEC_FLAG_GLOBAL_HEADER;
그러면 libx264에서 설정된 옵션을 화면에 텍스트로 뿌려 줍니다.
[libx264 @ 0x974f020] 264 - core 116 r2057 0ba8a9c - H.264/MPEG-4 AVC codec - Copyleft 2003-2011 - http://www.videolan.org/x264.html - options: cabac=0 ref=1 deblock=1:0:0 analyse=0x1:0x111 me=dia subme=8 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=4 chroma_me=0 trellis=0 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 keyint=25 keyint_min=13 scenecut=0 intra_refresh=0 rc_lookahead=25 rc=abr mbtree=1 bitrate=10000 ratetol=1.0 qcomp=0.50 qpmin=10 qpmax=51 qpstep=4 ip_ratio=1.25 aq=1:1.00
H.264 영상은 SPS, PPS 정보를 가지고 있는데, 이 정보는 avcodec_encode_video() 함수를 맨 처음 호출할 때 인코딩된 영상데이터 제일 앞에 포함되어 있다.
그러나 SDP를 사용하거나 기타 등등 의 경우 SPS, PPS 정보를 따로 추출하여 사용해야 할 경우가 있다. 이럴 때 CODEC_FLAG_GLOBAL_HEADER 옵션을 사용하면 된다.
이 옵션을 설정한 다음에 avcodec_encode_video() 함수를 호출하면 SPS, PPS 정보가 들어있지 않게 된다. 따라서 아래 방법을 통하여 SPS, PPS 정보를 얻어야 한다.
206 /* open codec */
207 ret = avcodec_open(f->ctx, codec);
208 assert(!ret, "avcodec_open is failed!");
209
210 /* get sps, pps */
211 #if 0
212 trace_sprop(f->ctx);
213 #endif
214 f->extradata_size = f->ctx->extradata_size;
215 memcpy(f->extradata, f->ctx->extradata, f->ctx->extradata_size);
AVCodecContext 구조체 안에 extradata_size에는 SPS, PPS 크기정보가 들어있고, 실제 데이터는 extradata에 들어있다. 이 값은 avcodec_open() 호출한 후에 얻을 수 있다.
6. x264 라이브러리는 기본설정으로 SPS, PPS가 주기적으로 나온다.. 참고하시길....
주기적으로 나오는 것을 설정하는 방법은 모름.
7. x264에 보면 아래와 같은 SEI 정보를 생성하여 인코딩된 영상에 들어가게 된다.
264 - core 116 r2057 0ba8a9c - H.264/MPEG-4 AVC codec - Copyleft 2003-2011 -http://www.videolan.org/x264.html - options: cabac=0 ref=1 deblock=1:0:0 analyse=0x1:0x111 me=dia subme=8 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=4 chroma_me=0 trellis=0 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 keyint=25 keyint_min=13 scenecut=0 intra_refresh=0 rc_lookahead=25 rc=abr mbtree=1 bitrate=10000 ratetol=1.0 qcomp=0.50 qpmin=10 qpmax=51 qpstep=4 ip_ratio=1.25 aq=1:1.00
- SEI 라는 것은 사용자가 독자적으로 정의하는 정보인데 x264가 이러한 정보를 넣는다.
테스트 결과 이 정보가 없어도 인코딩된 영상을 디코딩하는데 아무런 문제가 없다.
x264 API를 통하여서는 이 정보를 제거할 수는 없는 것 같다.
아래는 실제 설정하는 코드가 위치하는 곳이다.
int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal )
{
...
/* identify ourselves */
x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
if( x264_sei_version_write( h, &h->out.bs ) )
return -1;
if( x264_nal_end( h ) )
return -1;
...
}
- FFmpeg에서는 libavcodec/libx264.c 라는 파일에서 x264와의 I/F를 정의하고 있다. 아래는 코드다테스트 결과 이 정보가 없어도 인코딩된 영상을 디코딩하는데 아무런 문제가 없다.
x264 API를 통하여서는 이 정보를 제거할 수는 없는 것 같다.
아래는 실제 설정하는 코드가 위치하는 곳이다.
int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal )
{
...
/* identify ourselves */
x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
if( x264_sei_version_write( h, &h->out.bs ) )
return -1;
if( x264_nal_end( h ) )
return -1;
...
}
avctx->extradata = av_malloc(s);
avctx->extradata_size = encode_nals(avctx, avctx->extradata, s, nal, nnal, 1);
마지막 인자의 값을 1 을 설정하면 avcodec_encode_video() 함수 호출 시에 SEI 정보가 나오고, 0으로 설정하면, extradata안에 SEI 정보가 들어있게 된다.
피드 구독하기:
글 (Atom)