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 ¶
|
"It seems strange to meet computer geeks who're still primarily running Windows... as if they were still cooking on a wood stove or something." - mbp |










