MPlayer Codec
1. 문서의 목적 및 개괄 ¶문서를 작성하는 목적은 살펴본 내용을 까먹지 않고 정리하기 위함이 첫째이며, 같은 삽질을 하고자 하시는 분들에게 도움을 드리고자 함이 두 번째이다. 이 문서에서는 H.264 소프트웨어 코덱(FFMPEG) 분석과 하드웨어 코덱(Vendor Specific) 라이브러리의 추가 방법을 다루고자 한다. 시간이 될 경우 MPEG 등의 다른 코덱이나, MEncoder 등도 살펴볼 수도 있다.
MPlayer는 FFMPEG의 library 들을 사용한다. MPlayer 소스코드 내의 libavcodec 이 코덱 부분을 가지며, libavformat 부분이 미디어 파일을 파싱하는 역할을 한다. 많은 수의 소프트웨어 코덱들을 지원한다. 하드웨어와 연관된 부분으로 XVMC(X Video Motion Compensation) 옵션이 있는 데 이것은 Motion Compensation을 지원하는 Hardware가 있는 경우에 사용할 수 있다.
2. Copyright and Acknowledgements ¶This document is copyright (c) Kwangwoo Lee (kwangwoo.lee at gmail dot com). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License.
6. Video Decoder ¶좀 많이 생략 mplayer.c::main() 은 다음과 같다. 이 부분이 시작이며, open_stream(), demux_open(), video_read_properties(), reinit_video_chain(), update_video() 등의 함수를 주의 깊게 살펴봐야 한다. 특히 실제 decode가 일어나고 보여지는 부분은 update_video() 함수 내에서 일어나며, 앞의 open_stream(), demux_open() 등의 함수는 파일을 파싱하여 코덱을 선택하고 읽어 들이는 일을 한다.
mplayer.c
main() { mpctx->stream = open_stream(filename, 0, &mpctx->file_format); initialized_flags |= INITIALIZED_STREAM; // get sh_video_t and sh_audio_t instance and initialize them. // get width and height information for video mpctx->demuxer = demux_open(mpctx->stream, mpctx->file_format, audio_id, video_id, dvdsub_id, filename); if (mpctx->demuxer && mpctx->demuxer->type == DEMUXER_TYPE_PLAYLIST) { initialized_flags |= INITIALIZED_DEMUXER; } mpctx->d_audio = mpctx->demuxer->audio; mpctx->d_video = mpctx->demuxer->video; mpctx->d_sub = mpctx->demuxer->sub; select_audio(mpctx->demuxer, audio_id, audio_lang); mpctx->sh_audio = mpctx->d_audio->sh; mpctx->sh_video = mpctx->d_vidio->sh; if (mpctx->sh_vidio) { if (! video_read_properties(mpctx->sh_video) ) { … } elsle { mp_msg(MSGT_CPLAYER, MSGL_V, ”[V] filefmt:%d fourcc:0x%X size:%dx%d fps:%5.2f ftime:=%6.4f\n”, mpctx->demuxer->file_format, mpctx->sh_video->format, mpctx->sh_video->disp_w, mpctx->sh_video->disp_h, mpctx->sh_vidio->fps, mpctx->sh_video->frametime); } } demux_info_print(mpctx->demuxer); // init vo, vf // call init_best_video_codec(),init_video(),init() in vd_ffmpeg.c reinit_video_chain(); main: // setup audio if (mpctx->sh_audio) reinit_audio_chain(); // play audio if (mpctx->sh_audio) fill_audio_out_buffers(); if (!mpctx->sh_video) { … } else { //play video if (!mpctx->num_buffered_frames) { double frame_time = update_video(&blit_frame); mp_dbg(MSGT_AVSYNC,MSGL_DBG2, ”*** ftime=%5.3f ***\n”, frame_time); if (mpctx->sh_video->vf_initialized < 0) { mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_NotInitializedVOPorVO); mpctx->eof = 1; goto goto_next_file; } if (frame_time < 0) mpctx->eof = 1; else { mpctx->num_buffered_frames += blit_frame; // for nosound time_frame += frmae_time / playback_speed; } } } … } 6.1. MP4 - H.264 Container Format Example ¶MP4 파일 형식은 H.264 video stream을 담고 있을 수 있다. sh->format 부분에 avc1 이라는 정보를 가지고 있다. 이 포멧에서 주의해야 할 점은 SPS(Sequence Parameter Set)과 PPS(Picture Parameter Set)이 avcC 라는 Meta Tag 부분에 있다는 것이다. 이 경우 MPlayer 코드 상에서는 extradata로 처리한다는 것이다.
코덱의 decode() 함수는 sh_video_t 타입을 가지는 sh를 인자로 받게 되는 데 MP4 파일의 경우에는 다음과 같이 avcC Meta Tag의 데이터를 찾아서 쓸 수 있다. 이 데이터는 MPlayer가 파일을 파싱할 때 채워 넣어 진 정보이다.
avcc_size = sh->bih->biSize - sizeof(BITMAPINFOHEADER);
avcc = (unsigned char *) (sh->bih + 1); 이 파일 형식에는 NAL Indicator(0x000001)가 없다. 각 Frame의 제일 앞에 오는 4 Bytes 정보는 NAL의 크기이다. 이 파일 형식에 대한 참조는 Apple의 Quicktime File Format 관련 문서를 참조하길 바란다.
6.2. H.264 Decoder (-vfm ffmpeg) ¶update_vedio() 에서 generate_video_frame()을 호출한다. generate_video_frame() 내에서 decode_video()를 통해 frame을 decode 하고, filter_video()를 통해 video filter들을 적용한 후 마지막 filter에 해당하는 vo filter를 통해 출력한다. vo filter는 video out을 뜻한다.
mplayer.c
generate_video_frame() { // get demux_packet_t buffer ptr in &start in_size = ds_get_packet_pts(d_video, &start, &pts); decode_video(); filter_video(); } decode_video() 함수 내의 mpi가 decode 된 영상을 가지고 있다.
dec_video.c
decode_video() { // start has demux_packet_t dp. // It seems to be started with start sync (0x00000x). // Why not 0x000001? mpi = mpvdec->decode(sh_video, start, in_size, drop_frame); } mpvdec->decode() 함수는 초기화 시 파일을 읽어 선택된 코덱의 decode 함수를 호출하게된다. 모든 코덱들은 decode() 함수를 가지며 함수 포인터로 등록되어 있다.
libavcodec/h264.c
AVCodec h264_decoder = { “h264”, CODEC_TYPE_VIDEO, CODEC_ID_H264, sizeof(H264Context), decode_init, NULL, decode_end, decode_frame, CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY, .flush = flush_dpb, };
vd_ffmpeg.c
decode() { mpcodecs_get_image(); avcodec_decode_video(); } libavcodec/utils.c avcodec_decode_video() { avctx->codec->decode(); } H.264 형식의 파일은 NAL이란 단위로 decode 된다.
libavcodec/h264.c
decode_frame() { decode_nal_units(); execute_ref_pic_marking(); if (!FIELD_PICTURE) ff_er_frame_end(); MPV_frame_end(); // HAVE_XVMC return get_consumed_bytes(); } libavcodec/h264.c decode_nal_units() { decode_nal(); decode_rsbp_trailing(); decode_slice_header(); // loop execute_decode_slices(); } 6.3. Video Filter ¶display를 위한 vo filter에서 지원하는 colorspace와 decode 되어 나온 frame의 colorspace가 맞지 않는 경우 혹은 display 크기가 맞지 않는 경우 swscale filter가 자동으로 동작한다. 이 filter는 필요한 경우 software 적으로 colorspace conversion과 scaling을 한다.
mplayer 실행시 -vo fbdev 옵션을 사용한다면, vo filter로 frame buffer를 사용한다는 의미이다.
7. Links ¶
|
You have a deep appreciation of the arts and music. |