· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
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.

3. 주의사항


MPlayer License는 GPL 이다. 수정 후 배포가 일어날 경우에는 Source Code를 GPL하에 다시 배포해야 한다. 이는 codec library만을 추가한다고 해도 마찬가지의 효과를 가진다. Hardware video codec을 사용하기 위한 libary를 작성하고 MPlayer에서 그것을 사용한다고 해도 GPL의 적용을 받는다.

4. Reading List


MPlayer codec 관련 작업시 꼭 봐야할 문서 libavcodec 과 libavformat 관련 작업 시 참고해야 할 문서

5. 실행 방법


* mplayer -vfm ffmpeg -vo fbdev -nosound

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를 사용한다는 의미이다.




sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2009-04-16 13:48:09
Processing time 0.0081 sec