[[TableOfContents]] == ¹®¼­ÀÇ ¸ñÀû ¹× °³°ý == ¹®¼­¸¦ ÀÛ¼ºÇÏ´Â ¸ñÀûÀº »ìÆ캻 ³»¿ëÀ» ±î¸ÔÁö ¾Ê°í Á¤¸®Çϱâ À§ÇÔÀÌ Ã¹Â°À̸ç, °°Àº »ðÁúÀ» ÇÏ°íÀÚ ÇϽô ºÐµé¿¡°Ô µµ¿òÀ» µå¸®°íÀÚ ÇÔÀÌ µÎ ¹ø°ÀÌ´Ù. ÀÌ ¹®¼­¿¡¼­´Â H.264 ¼ÒÇÁÆ®¿þ¾î ÄÚµ¦(FFMPEG) ºÐ¼®°ú Çϵå¿þ¾î ÄÚµ¦(Vendor Specific) ¶óÀ̺귯¸®ÀÇ Ãß°¡ ¹æ¹ýÀ» ´Ù·ç°íÀÚ ÇÑ´Ù. ½Ã°£ÀÌ µÉ °æ¿ì MPEG µîÀÇ ´Ù¸¥ ÄÚµ¦À̳ª, MEncoder µîµµ »ìÆ캼 ¼öµµ ÀÖ´Ù. MPlayer´Â FFMPEGÀÇ library µéÀ» »ç¿ëÇÑ´Ù. MPlayer ¼Ò½ºÄÚµå ³»ÀÇ libavcodec ÀÌ ÄÚµ¦ ºÎºÐÀ» °¡Áö¸ç, libavformat ºÎºÐÀÌ ¹Ìµð¾î ÆÄÀÏÀ» ÆĽÌÇÏ´Â ¿ªÇÒÀ» ÇÑ´Ù. ¸¹Àº ¼öÀÇ ¼ÒÇÁÆ®¿þ¾î ÄÚµ¦µéÀ» Áö¿øÇÑ´Ù. Çϵå¿þ¾î¿Í ¿¬°üµÈ ºÎºÐÀ¸·Î XVMC(X Video Motion Compensation) ¿É¼ÇÀÌ ÀÖ´Â µ¥ ÀÌ°ÍÀº Motion CompensationÀ» Áö¿øÇÏ´Â Hardware°¡ ÀÖ´Â °æ¿ì¿¡ »ç¿ëÇÒ ¼ö ÀÖ´Ù. == 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. == ÁÖÀÇ»çÇ× == MPlayer License´Â GPL ÀÌ´Ù. ¼öÁ¤ ÈÄ ¹èÆ÷°¡ ÀϾ °æ¿ì¿¡´Â Source Code¸¦ GPLÇÏ¿¡ ´Ù½Ã ¹èÆ÷ÇØ¾ß ÇÑ´Ù. ÀÌ´Â codec library¸¸À» Ãß°¡ÇÑ´Ù°í Çصµ ¸¶Âù°¡ÁöÀÇ È¿°ú¸¦ °¡Áø´Ù. Hardware video codecÀ» »ç¿ëÇϱâ À§ÇÑ libary¸¦ ÀÛ¼ºÇÏ°í MPlayer¿¡¼­ ±×°ÍÀ» »ç¿ëÇÑ´Ù°í Çصµ GPLÀÇ Àû¿ëÀ» ¹Þ´Â´Ù. == Reading List == MPlayer codec °ü·Ã ÀÛ¾÷½Ã ²À ºÁ¾ßÇÒ ¹®¼­ * http://www.mplayerhq.hu/DOCS/tech/ libavcodec °ú libavformat °ü·Ã ÀÛ¾÷ ½Ã Âü°íÇØ¾ß ÇÒ ¹®¼­ * http://ffmpeg.mplayerhq.hu/documentation.html == ½ÇÇà ¹æ¹ý == * mplayer -vfm ffmpeg -vo fbdev -nosound == Video Decoder == Á» ¸¹ÀÌ »ý·« mplayer.c::main() Àº ´ÙÀ½°ú °°´Ù. ÀÌ ºÎºÐÀÌ ½ÃÀÛÀ̸ç, open_stream(), demux_open(), video_read_properties(), reinit_video_chain(), update_video() µîÀÇ ÇÔ¼ö¸¦ ÁÖÀÇ ±í°Ô »ìÆìºÁ¾ß ÇÑ´Ù. ƯÈ÷ ½ÇÁ¦ decode°¡ ÀϾ°í º¸¿©Áö´Â ºÎºÐÀº update_video() ÇÔ¼ö ³»¿¡¼­ ÀϾ¸ç, ¾ÕÀÇ open_stream(), demux_open() µîÀÇ ÇÔ¼ö´Â ÆÄÀÏÀ» ÆĽÌÇÏ¿© ÄÚµ¦À» ¼±ÅÃÇÏ°í ÀÐ¾î µéÀÌ´Â ÀÏÀ» ÇÑ´Ù. {{{#!vim c 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; } } } ¡¦ } }}} === 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°¡ ÆÄÀÏÀ» ÆĽÌÇÒ ¶§ ä¿ö ³Ö¾î Áø Á¤º¸ÀÌ´Ù. {{{#!vim c avcc_size = sh->bih->biSize - sizeof(BITMAPINFOHEADER); avcc = (unsigned char *) (sh->bih + 1); }}} ÀÌ ÆÄÀÏ Çü½Ä¿¡´Â NAL Indicator(0x000001)°¡ ¾ø´Ù. °¢ FrameÀÇ Á¦ÀÏ ¾Õ¿¡ ¿À´Â 4 Bytes Á¤º¸´Â NALÀÇ Å©±âÀÌ´Ù. ÀÌ ÆÄÀÏ Çü½Ä¿¡ ´ëÇÑ ÂüÁ¶´Â AppleÀÇ Quicktime File Format °ü·Ã ¹®¼­¸¦ ÂüÁ¶ÇÏ±æ ¹Ù¶õ´Ù. * http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt === 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À» ¶æÇÑ´Ù. {{{#!vim c 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 µÈ ¿µ»óÀ» °¡Áö°í ÀÖ´Ù. {{{#!vim c 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() ÇÔ¼ö¸¦ °¡Áö¸ç ÇÔ¼ö Æ÷ÀÎÅÍ·Î µî·ÏµÇ¾î ÀÖ´Ù. {{{#!vim c 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, }; }}} {{{#!vim c vd_ffmpeg.c decode() { mpcodecs_get_image(); avcodec_decode_video(); } libavcodec/utils.c avcodec_decode_video() { avctx->codec->decode(); } }}} H.264 Çü½ÄÀÇ ÆÄÀÏÀº NALÀ̶õ ´ÜÀ§·Î decode µÈ´Ù. {{{#!vim c 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(); } }}} === Video Filter === display¸¦ À§ÇÑ vo filter¿¡¼­ Áö¿øÇÏ´Â colorspace¿Í decode µÇ¾î ³ª¿Â frameÀÇ colorspace°¡ ¸ÂÁö ¾Ê´Â °æ¿ì ȤÀº display Å©±â°¡ ¸ÂÁö ¾Ê´Â °æ¿ì swscale filter°¡ ÀÚµ¿À¸·Î µ¿ÀÛÇÑ´Ù. ÀÌ filter´Â ÇÊ¿äÇÑ °æ¿ì software ÀûÀ¸·Î colorspace conversion°ú scalingÀ» ÇÑ´Ù. mplayer ½ÇÇà½Ã -vo fbdev ¿É¼ÇÀ» »ç¿ëÇÑ´Ù¸é, vo filter·Î frame buffer¸¦ »ç¿ëÇÑ´Ù´Â ÀǹÌÀÌ´Ù. == Links == * http://docs.google.com/Present?docid=dhf2pf26_62dkvcbkht&skipauth=true : function call sequence