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.
4. Reading List ¶MPlayer codec °ü·Ã ÀÛ¾÷½Ã ²À ºÁ¾ßÇÒ ¹®¼
libavcodec °ú libavformat °ü·Ã ÀÛ¾÷ ½Ã Âü°íÇØ¾ß ÇÒ ¹®¼
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 ¶
|
Be careful how you get yourself involved with persons or situations that can't bear inspection. |