강좌 & 팁
1. ARM PC 에서 ffmpeg를 이용하여 영상 스트리밍 하기
4월에 발매할 ARM PC-V210 를 이용하여, 영상과 관련된 스트리밍 서비스를 해보고, 이 결과를 G100-S5PV210 보드에서의 동작을 해보도록 하겠습니다.
ARM PC-V210 를 이용하여 영상 스트리밍과 관련된 작업을 수행 하기 위하여 우선 ffmpeg를 다운로드 하는것 부터 작업을 진행 하도록 하겠습니다.
ARM PC-V210 에서 ffmpeg를 다운로드 하기 위하여 git 프로그램이 필요하며, git 프로그램을 다음의 명령어를 실행 하여, 설치 합니다.
# apt-get install git 패키지 목록을 읽는 중입니다... 완료 의존성 트리를 만드는 중입니다 상태 정보를 읽는 중입니다... 완료 다음 패키지를 더 설치할 것입니다: emacsen-common git-man liberror-perl rsync 제안하는 패키지: git-doc git-el git-arch git-cvs git-svn git-email git-daemon-run git-gui gitk gitweb 다음 새 패키지를 설치할 것입니다: emacsen-common git git-man liberror-perl rsync 0개 업그레이드, 5개 새로 설치, 0개 제거 및 0개 업그레이드 안 함. 4,703 k바이트 아카이브를 받아야 합니다. 이 작업 후 9,974 k바이트의 디스크 공간을 더 사용하게 됩니다. 계속 하시겠습니까 [Y/n]? Y |
위의 명령을 이용하여 git 프로그램이 정상적으로 설치가 되었다면, git를 이용하여 다음의 명령어를 실행 하여, ffmpeg를 다운로드 하도록 하겠습니다.
# mkdir ffmpeg_src # cd ffmpeg_src # git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg Cloning into ffmpeg... remote: Counting objects: 293462, done. remote: Compressing objects: 100% (67351/67351), done. remote: Total 293462 (delta 232822), reused 285856 (delta 225643) Receiving objects: 100% (293462/293462), 71.92 MiB | 543 KiB/s, done. Resolving deltas: 100% (232822/232822), done. |
잠시 후, ffmpeg의 다운로드가 끝나게 되면, ffmpeg를 configure를 이용하여 설정을 합니다.
# ./configure --prefix=/root/ffmpeg_bin --enable-static --disable-shared --enable-ffserver --disable-doc --enable-version3 ... ( 설정 중 ) ... nstall prefix /root/ffmpeg_bin source path . C compiler gcc ARCH arm (armv7-a) big-endian no runtime cpu detection yes ARMv5TE enabled yes ARMv6 enabled yes ARMv6T2 enabled yes VFP enabled yes NEON enabled yes THUMB enabled yes debug symbols yes strip symbols yes optimize for size no optimizations yes static yes shared no postprocessing support no new filter support yes network support yes threading support pthreads safe bitstream reader yes SDL support no texi2html enabled no perl enabled yes pod2man enabled yes makeinfo enabled no External libraries: iconv Enabled decoders: aac c93 interplay_video aac_latm cavs jacosub aasc cdgraphics jpeg2000 ac3 cdxl jpegls adpcm_4xm cinepak jv adpcm_adx cljr kgv1 adpcm_afc cllc kmvc adpcm_ct comfortnoise lagarith adpcm_ea cook loco adpcm_ea_maxis_xa cpia mace3 adpcm_ea_r1 cscd mace6 adpcm_ea_r2 cyuv mdec adpcm_ea_r3 dca microdvd adpcm_ea_xas dfa mimic adpcm_g722 dirac mjpeg adpcm_g726 dnxhd mjpegb adpcm_ima_amv dpx mlp adpcm_ima_apc dsicinaudio mmvideo adpcm_ima_dk3 dsicinvideo motionpixels adpcm_ima_dk4 dvbsub movtext adpcm_ima_ea_eacs dvdsub mp1 adpcm_ima_ea_sead dvvideo mp1float adpcm_ima_iss dxtory mp2 adpcm_ima_oki eac3 mp2float adpcm_ima_qt eacmv mp3 adpcm_ima_smjpeg eamad mp3adu adpcm_ima_wav eatgq mp3adufloat adpcm_ima_ws eatgv mp3float adpcm_ms eatqi mp3on4 adpcm_sbpro_2 eightbps mp3on4float adpcm_sbpro_3 eightsvx_exp mpc7 adpcm_sbpro_4 eightsvx_fib mpc8 adpcm_swf escape124 mpeg1video adpcm_thp escape130 mpeg2video adpcm_xa evrc mpeg4 adpcm_yamaha ffv1 mpegvideo alac ffvhuff mpl2 als ffwavesynth msa1 amrnb flac msmpeg4v1 amrwb flic msmpeg4v2 amv flv msmpeg4v3 anm fourxm msrle ansi fraps mss1 ape frwu mss2 ass g723_1 msvideo1 asv1 g729 mszh asv2 gif mts2 atrac1 gsm mvc1 atrac3 gsm_ms mvc2 aura h261 mxpeg aura2 h263 nellymoser avrn h263i nuv avrp h263p paf_audio avs h264 paf_video avui huffyuv pam ayuv iac pbm bethsoftvid idcin pcm_alaw bfi idf pcm_bluray bink iff_byterun1 pcm_dvd binkaudio_dct iff_ilbm pcm_f32be binkaudio_rdft imc pcm_f32le bintext indeo2 pcm_f64be bmp indeo3 pcm_f64le bmv_audio indeo4 pcm_lxf bmv_video indeo5 pcm_mulaw brender_pix interplay_dpcm pcm_s16be pcm_s16be_planar rv20 v410 pcm_s16le rv30 vb pcm_s16le_planar rv40 vble pcm_s24be s302m vc1 pcm_s24daud sami vc1image pcm_s24le sanm vcr1 pcm_s24le_planar sgi vima pcm_s32be sgirle vmdaudio pcm_s32le shorten vmdvideo pcm_s32le_planar sipr vmnc pcm_s8 smackaud vorbis pcm_s8_planar smacker vp3 pcm_u16be smc vp5 pcm_u16le snow vp6 pcm_u24be sol_dpcm vp6a pcm_u24le sonic vp6f pcm_u32be sp5x vp8 pcm_u32le srt vplayer pcm_u8 subrip vqa pcm_zork subviewer wavpack pcx subviewer1 webp pgm sunrast webvtt pgmyuv svq1 wmalossless pgssub svq3 wmapro pictor tak wmav1 pjs targa wmav2 ppm targa_y216 wmavoice prores text wmv1 prores_lgpl theora wmv2 ptx thp wmv3 qcelp tiertexseqvideo wmv3image qdm2 tiff wnv1 qdraw tmv ws_snd1 qpeg truehd xan_dpcm qtrle truemotion1 xan_wc3 r10k truemotion2 xan_wc4 r210 truespeech xbin ra_144 tscc2 xbm ra_288 tta xface ralf twinvq xl rawvideo txd xsub realtext ulti xwd rl2 utvideo y41p roq v210 yop roq_dpcm v210x yuv4 rpza v308 zero12v rv10 v408 Enabled encoders: a64multi jpegls pgm a64multi5 ljpeg pgmyuv aac mjpeg ppm ac3 movtext prores ac3_fixed mp2 prores_anatoliy adpcm_adx mpeg1video prores_kostya adpcm_g722 mpeg2video qtrle adpcm_g726 mpeg4 r10k adpcm_ima_qt msmpeg4v2 r210 adpcm_ima_wav msmpeg4v3 ra_144 adpcm_ms msvideo1 rawvideo adpcm_swf nellymoser roq adpcm_yamaha pam roq_dpcm alac pbm rv10 amv pcm_alaw rv20 ass pcm_f32be sgi asv1 pcm_f32le snow asv2 pcm_f64be sonic avrp pcm_f64le sonic_ls avui pcm_mulaw srt ayuv pcm_s16be subrip bmp pcm_s16be_planar sunrast cljr pcm_s16le svq1 comfortnoise pcm_s16le_planar targa dca pcm_s24be tiff dnxhd pcm_s24daud utvideo dpx pcm_s24le v210 dvbsub pcm_s24le_planar v308 dvdsub pcm_s32be v408 dvvideo pcm_s32le v410 eac3 pcm_s32le_planar vorbis ffv1 pcm_s8 wmav1 ffvhuff pcm_s8_planar wmav2 flac pcm_u16be wmv1 flv pcm_u16le wmv2 g723_1 pcm_u24be xbm gif pcm_u24le xface h261 pcm_u32be xsub h263 pcm_u32le xwd h263p pcm_u8 y41p huffyuv pcx yuv4 jpeg2000 Enabled hwaccels: Enabled parsers: aac dvd_nav mpegvideo aac_latm dvdsub png ac3 flac pnm adx gsm rv30 bmp h261 rv40 cavsvideo h263 tak cook h264 vc1 dca mjpeg vorbis dirac mlp vp3 dnxhd mpeg4video vp8 dvbsub mpegaudio Enabled demuxers: aac idf pcm_u24le ac3 iff pcm_u32be act ilbc pcm_u32le adf image2 pcm_u8 adx image2pipe pjs aea ingenient pmp afc ipmovie pva aiff ircam pvf amr iss qcp anm iv8 r3d apc ivf rawvideo ape jacosub realtext aqtitle jv rl2 asf latm rm ass lmlm4 roq ast loas rpl au lvf rso avi lxf rtp avr m4v rtsp avs matroska sami bethsoftvid mgsts sap bfi microdvd sbg bink mjpeg sdp bintext mlp segafilm bit mm shorten bmv mmf siff brstm mov smacker c93 mp3 smjpeg caf mpc smush cavsvideo mpc8 sol cdg mpegps sox cdxl mpegts spdif concat mpegtsraw srt daud mpegvideo str dfa mpl2 subviewer dirac mpsub subviewer1 dnxhd msnwc_tcp swf dsicin mtv tak dts mv tedcaptions dtshd mvi thp dv mxf tiertexseq dxa mxg tmv ea nc truehd ea_cdata nistsphere tta eac3 nsv tty epaf nut txd ffm nuv vc1 ffmetadata ogg vc1t filmstrip oma vivo flac paf vmd flic pcm_alaw vobsub flv pcm_f32be voc fourxm pcm_f32le vplayer frm pcm_f64be vqf g722 pcm_f64le w64 g723_1 pcm_mulaw wav g729 pcm_s16be wc3 gif pcm_s16le webvtt gsm pcm_s24be wsaud gxf pcm_s24le wsvqa h261 pcm_s32be wtv h263 pcm_s32le wv h264 pcm_s8 xa hls pcm_u16be xbin ico pcm_u16le xmv idcin pcm_u24be xwma yop yuv4mpegpipe Enabled muxers: a64 image2pipe pcm_s16le ac3 ipod pcm_s24be adts ircam pcm_s24le adx ismv pcm_s32be aiff ivf pcm_s32le amr jacosub pcm_s8 asf latm pcm_u16be asf_stream m4v pcm_u16le ass matroska pcm_u24be ast matroska_audio pcm_u24le au md5 pcm_u32be avi microdvd pcm_u32le avm2 mjpeg pcm_u8 bit mkvtimestamp_v2 psp caf mlp rawvideo cavsvideo mmf rm crc mov roq daud mp2 rso dirac mp3 rtp dnxhd mp4 rtsp dts mpeg1system sap dv mpeg1vcd segment eac3 mpeg1video smjpeg f4v mpeg2dvd smoothstreaming ffm mpeg2svcd sox ffmetadata mpeg2video spdif filmstrip mpeg2vob srt flac mpegts stream_segment flv mpjpeg swf framecrc mxf tee framemd5 mxf_d10 tg2 g722 null tgp g723_1 nut truehd gif ogg vc1 gxf oma vc1t h261 pcm_alaw voc h263 pcm_f32be w64 h264 pcm_f32le wav hls pcm_f64be webm ico pcm_f64le wtv ilbc pcm_mulaw wv image2 pcm_s16be yuv4mpegpipe Enabled protocols: cache hls rtmp concat http rtmpt crypto httpproxy rtp data md5 srtp ffrtmphttp mmsh tcp file mmst udp gopher pipe Enabled filters: aconvert channelsplit nullsink aevalsrc color nullsrc afade concat overlay aformat copy pad allpass crop pan alphaextract curves perms alphamerge deshake pixdesctest amerge drawbox removelogo amix earwax rgbtestsrc amovie edgedetect scale anull equalizer select anullsink fade sendcmd anullsrc field setdar apad fieldorder setfield aperms format setpts aresample fps setsar aselect framestep settb asendcmd gradfun showinfo asetnsamples hflip showspectrum asetpts highpass showwaves asettb histogram silencedetect ashowinfo idet sine asplit il smptebars astreamsync join split atempo life swapuv bandpass lowpass testsrc bandreject lut thumbnail bass lutrgb tile bbox lutyuv transpose biquad mandelbrot treble blackdetect movie unsharp blend negate vflip cellauto noformat volume channelmap null volumedetect Enabled bsfs: aac_adtstoasc mjpeg2jpeg mp3_header_decompress chomp mjpega_dump_header noise dump_extradata mov2textsub remove_extradata h264_mp4toannexb mp3_header_compress text2movsub imx_dump_header Enabled indevs: dv1394 lavfi v4l2 fbdev oss Enabled outdevs: oss License: LGPL version 3 or later Creating config.mak and config.h... |
위와 같이 설정을 모두 마친 후, 다음과 같이 make 명령어를 이용하여 컴파일을 수행 합니다.
# make ... ( 컴파일 중 ) ... CC ffmpeg.o ffmpeg.c: In function ‘write_frame’: ffmpeg.c:583:9: warning: ‘destruct’ is deprecated (declared at ./libavcodec/avcodec.h:1064) CC ffmpeg_opt.o CC ffmpeg_filter.o CC cmdutils.o LD ffmpeg_g CP ffmpeg STRIP ffmpeg CC ffprobe.o ffprobe.c: In function ‘value_string.clone.4.clone.6’: ffprobe.c:170:19: warning: ‘vali’ may be used uninitialized in this function LD ffprobe_g CP ffprobe STRIP ffprobe CC ffserver.o LD ffserver_g CP ffserver STRIP ffserver |
위와 같이 컴파일이 모두 끝나게 되면, make install 명령을 수행하여 install을 합니다. ( prefix에서 설정한 디렉토리에 install을 합니다. )
# make install ... ( 인스톨 중 ) ... INSTALL libavutil/version.h INSTALL libavutil/xtea.h INSTALL libavutil/lzo.h INSTALL libavutil/avconfig.h INSTALL libavutil/libavutil.pc |
설치를 모두 마친 상태에서 ldd 명령을 이용 하여 바이너리에 연관되어 있는 라이브러리를 확인해 보도록 하겠습니다.
# ldd /root/ffmpeg_bin/bin/ffmpeg libm.so.6 => /lib/arm-linux-gnueabi/libm.so.6 (0x2aabc000) librt.so.1 => /lib/arm-linux-gnueabi/librt.so.1 (0x2ab29000) libpthread.so.0 => /lib/arm-linux-gnueabi/libpthread.so.0 (0x2ab37000) libc.so.6 => /lib/arm-linux-gnueabi/libc.so.6 (0x2ab4b000) /lib/ld-linux.so.3 (0x54aaa000) # ldd /root/ffmpeg_bin/bin/ffserver libdl.so.2 => /lib/arm-linux-gnueabi/libdl.so.2 (0x2aabc000) libm.so.6 => /lib/arm-linux-gnueabi/libm.so.6 (0x2aac8000) libpthread.so.0 => /lib/arm-linux-gnueabi/libpthread.so.0 (0x2ab34000) libc.so.6 => /lib/arm-linux-gnueabi/libc.so.6 (0x2ab48000) /lib/ld-linux.so.3 (0x54aaa000) |
static 으로 빌드를 하였기 때문에, 위와 같이 동적으로 참고 하는 라이브러리는 기본적인 것 이외에는 없는 것을 확인 할 수 있습니다.
생성된 ffmpeg과 ffserver 바이너리 파일을 이용하여, USB WebCam과 연동하여 작업을 수행 해보도록 하겠습니다.본 강좌에서 사용할 USB WebCam은 Logitech 에서 나온 QuickCam 입니다.
USB WebCam에 대한 상세한 정보는 다음의 페이지에서 확인 하시기 바랍니다.
http://www.logitech.com/en-in/product/quickcam-sphere-af?crid=34
USB WebCam을 ARM PC 본체에 연결을 합니다. 그리고 사용할 디바이스 노드 파일도 확인을 해보도록 하겠습니다.
# ls -al /dev/video0 crw-rw----+ 1 root video 81, 0 2013-03-27 11:11 /dev/video0 |
ffserver를 이용하기 위하여 /root/ffmpeg_bin/bin/ffserver.conf 파일의 내용을 다음과 같이 작성 합니다.
Port 8090 # bind to all IPs aliased or not BindAddress 0.0.0.0 # max number of simultaneous clients MaxClients 1000 # max bandwidth per-client (kb/s) MaxBandwidth 10000 # Suppress that if you want to launch ffserver as a daemon. NoDaemon <Feed feed1.ffm> File /tmp/feed1.ffm FileMaxSize 100M </Feed> <Stream test.swf> Feed feed1.ffm Format swf VideoCodec flv VideoFrameRate 30 VideoBufferSize 80000 VideoBitRate 100 VideoQMin 1 VideoQMax 5 #VideoSize 160x160 VideoSize 640x480 PreRoll 0 Noaudio </Stream> |
ARM PC 에서 다음과 아래의 명령어를 이용하여 실행을 합니다.
# /root/ffmpeg_bin/bin/ffserver -f /root/ffmpeg_bin/bin/ffserver.conf & # /root/ffmpeg -r 20 -s 640x480 -f video4linux2 -i /dev/video0 http://localhost:8090/feed1.ffm |
위와 같이 실행이 되고 있는 상태에서, 윈도우의 곰 플레이어(혹은 다른 동영상 플레이어)를 이용하여 동영상이 출력 되는지 확인을 해봅니다.
http://192.168.4.43:8090/test.swf
동영상 출력시 대략 3-5초 정도의 딜레이가 생깁니다.
테스트가 끝나면 ffmpeg관련 바이너리 파일을 NFS 디렉토리에 복사를 합니다.
# cp -a /root/ffmpeg_bin /nfs/. |
2. G100 보드의 커널 수정 하기
G100 보드에서 ARM PC에서 사용하였던 USB WebCam을 인식 시키기 위하여 커널의 메뉴 컨피그를 다음과 같이 수정합니다.
# wget ftp://ftp.falinux.com/kernel/recommendation/linux-2.6.35-s5pv210.tar.gz # tar xvfz linux-2.6.35-s5pv210.tar.gz # cd linux-2.6.35-s5pv210 # ./make_s5pv210.sh menuconfig |
커널 옵션을 다음과 같이 수정 합니다.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Device Drivers --->
<*> Multimedia support --->
[*] Video capture adapters --->
[*] V4L USB devices (NEW) --->
<*> USB Video Class (UVC)
<*> GSPCA based webcams --->
<*> OV51x / OVFX2 / W996xCF USB Camera Driver
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
수정된 내용을 적용 하기 위하여 커널을 빌드하여, 빌드된 커널이미지를 G100 보드에 다운로드 합니다.
# ./make_s5pv210.sh zImge |
위의 명령을 수행 하여 수정된 g100 커널 이미지가 생성되었다면, EZBOOT의 TFK 명령을 이용하여 생성한 커널 이미지를 새로 G100 보드에 다운로드 합니다.
1, 2절 에서 작업한 결과를 이용하여 ffmpeg를 위하여 실행 바이너리와 G100 보드에 커널까지 동작하게 되었습니다.
이를 바탕으로 G100 보드에서의 실행 작업을 진행 하도록 하겠습니다.
우선 G100 보드를 부팅 시킨 후, 다음과 같이 root로 로그인을 합니다.
Welcome to FALinux (www.falinux.com) Linux Kernel 2.6.35-falinux falinux login: root [root@falinux ~]$ |
[root@falinux ~]$ ./nfsmnt 192.168.4.43 >> 192.168.4.43 [root@falinux ~]$ |
마운트가 끝난 후 실행 파일을 먼저 /app 디렉토리로 복사를 합니다.
[root@falinux ~]$ cp -a /nfs/ffmpeg_bin /app/. |
실행 파일의 복사가 끝난 후, USB WebCam을 위하여, /dev/video0 노드 파일을 생성 합니다.
[root@falinux ~]$ mknod /dev/video0 c 81 0 |
Port 8090 # bind to all IPs aliased or not BindAddress 0.0.0.0 # max number of simultaneous clients MaxClients 1000 # max bandwidth per-client (kb/s) MaxBandwidth 10000 # Suppress that if you want to launch ffserver as a daemon. NoDaemon <Feed feed1.ffm> File /app/ffmpeg_bin/feed1.ffm <--- 수정 부분 FileMaxSize 100M </Feed> <Stream test.swf> Feed feed1.ffm Format swf VideoCodec flv VideoFrameRate 30 VideoBufferSize 80000 VideoBitRate 100 VideoQMin 1 VideoQMax 5 #VideoSize 160x160 VideoSize 640x480 PreRoll 0 Noaudio </Stream> |
수정한 내용을 기반으로 하여 프로그램을 G100 보드에서 실행 합니다.
[root@falinux ~]$ cd /app/ffmpeg_bin
[root@falinux ~]$ ./ffserver -f ./ffserver.conf &
[root@falinux ~]$ ./ffmpeg -r 20 -s 640x480 -f video4linux2 -i /dev/video0 http://localhost:8090/feed1.ffmffmpeg version N-51338-g914f48d Copyright (c) 2000-2013 the FFmpeg developers built on Mar 27 2013 13:17:43 with gcc 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4) configuration: --prefix=/root/ffmpeg_bin --enable-static --disable-shared --e3 libavutil 52. 22.101 / 52. 22.101 libavcodec 55. 1.100 / 55. 1.100 libavformat 55. 0.100 / 55. 0.100 libavdevice 55. 0.100 / 55. 0.100 libavfilter 3. 48.105 / 3. 48.105 libswscale 2. 2.100 / 2. 2.100 libswresample 0. 17.102 / 0. 17.102 [video4linux2,v4l2 @ 0xc7b4b0] Estimating duration from bitrate, this may be ine Input #0, video4linux2,v4l2, from '/dev/video0': Duration: N/A, start: 628.615000, bitrate: 98304 kb/s Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 640x480, 98304 kc Output #0, ffm, to 'http://localhost:8090/feed1.ffm': Metadata: creation_time : now encoder : Lavf55.0.100 Stream #0:0: Video: flv1, yuv420p, 640x480, q=1-5, 100 kb/s, 1000k tbn, 20 c Stream mapping: Stream #0:0 -> #0:0 (rawvideo -> flv) Press [q] to stop, [?] for help frame= 467 fps= 18 q=31.0 Lsize= 2348kB time=00:00:23.35 bitrate= 823.8kbit video:2328kB audio:0kB subtitle:0 global headers:0kB muxing overhead 0.878149% Received signal 2: terminating.
|
4. 미디어 플레이어를 이용하여 확인 하기.
위와 같이 실행이 되고 있는 상태에서, 윈도우의 곰 플레이어(혹은 다른 동영상 플레이어)를 이용하여 동영상이 출력 되는지 확인을 해봅니다.
http://192.168.10.210:8090/test.swf
동영상 출력시 대략 3-5초 정도의 딜레이가 생깁니다.
이상으로, ARM PC 에서 생성한 바이너리를 이용하여 G100 보드에서 동작 시키기를 수행 하였습니다.