sleepbysleep
Debian Firewalls -- The Firewall ¶from http://www.cyberdogtech.com/firewalls/tutorial.php?page=fw Copyright © 2006 Matt LaPlante. All rights reserved. 리눅스 커널 2.6은 iptables을 방화벽기능으로 제공하고 있다. iptables에 관한 더 많은 정보는 http://www.netfilter.org을 보라. iptables은 놀랄만할 정도로 견고하고 실용적인 방화벽 패키지이다. 그리고 우리 기계의 방화벽과 라우팅 기능 모두릐 핵심을 이룰것이다. iptables은 최소사양 데비안 설치시에 기본으로 설치된다. 그래서 더이상의 설치는 필요 없다.
iptables의 전신인 ipchains도 기본적으로 설치되지만 우리 시스템에는 필요하지 않다. 난 간결하고 정돈된 상태를 유지하기 위해서 지울것을 추천한다.
Firewall:~# apt-get remove ipchainsiptables는 놀랄정도로 막강하지만 불행히도 그 파워는 대가를 지불해야 생긴다. ...이름하여 설정. 기능적으로 일일이 설정할 수 있지만, iptables의 설정은 사람이 읽지 못한다. 간단히 말해서 매우 복잡하고 빨리 지치게 만들 수 있다. 다행히도 우리는 shorewall이라는 프로그램 형식에서 해답을 찾을 수 있다. shorewall 은 Tom Eastep에 의해서 쓰여졌고 http://shorewall.sourceforge.net에서 구할 수 있다. 물론 우리도 shorewall을 위한 데비안 패키지를 받는다. 그래서 일일이 다운로드하고 설치할 필요는 없다. 시작하기 위해서 shorewall package를 설치하기 위해서 apt-get을 이용하자. Firewall:~# apt-get install shorewall 주의요망: 소개에서 언급한데로, 이 듀토리얼은 데비안 3.1"Sarge"시스템에 기반한다. 모든 리눅스 오퍼레이팅 시스템은 다른 패키지 셋과 릴리즈 주기를 사용한다. (패키지 이름이 비록 같을지라도) 이것은 데비안 기반의 우분투도에도 해당한다. 이건 다른 오퍼레이팅 시스템을 사용한다면 다른 소프트웨어 버전을 사용할지도 모른다는걸 의미한다. 이것때문에 튜토리얼 예제는 말한대로 작동하지 않을 수도 있다. 여기에 있는 예제들은 현재 데비안 stable 버전에서 shorewall 2.2의 작동을 가정한다. 만약 당신의 배포판이 다른 버전이라면, 당신은 제품 문서를 읽어서 예제들을 바꿀 수 있어야 한다.이시점에서 apt는 shorewall에 구속되는 2개의 추가적인 패키지를 설치해야 한다고 말말할지 모른다. 이건 정상이고 당신은 모든것을 설치하도록 패키지 설정을 승락해야한다. "제안된"패키지들에 대해서 걱정하지 말아라. 우리는 그것이 필요하지 않다. 추가적인 주의! - shorewall iptables 설정의 문제는 새로운것이 없고 모든 작업을 수행하는 것과 마찬가지로 문제를 해결하는데 한가지 이상의 방법이 있다. 이 튜토리얼은 그 따분한 작업을 하는데 shorewall을 사용하지만 같은 작업을 하는 다른 프로그램등 여기저기에 있다. 대신 많이 사용하는 것이 FireHOL이다 (http://firehol.sourceforge.net). 만약 shorewall이 당신의 보트를 떠오르지 못하도록 한다면 대체물들은 항상 있다.진행하기전에 두가지의 공통된 잘못된 개념들을 확실히하자: shorewall은 방화벽이 아니다. 그리고 사실 이건 어플리케이션조차도 아니다. 프로그램이나 데몬의 공통된 개념은 계속 수행하는 어플리케이션중 하나다. 이것은 Shorewall의 경우에 맞지 않다. 대신 Shorewall은 실제 한번 수행하고 끝마치는 그져 매우 큰 규모의 script모음이다. Shorewall 그 자체는 어떤 방화벽 작업도 하지 못한다; 단순히 당신의 요구에 맞게 iptables을 설정하고 끝마친다. 이제부터 설정에 들어가자. 당신은 아마도 Shorewall 설치 마지막에 당신에게 알려준 이 프로그램은 /etc/default/shorewall 파일을 변경하지 않으면 시작되지 않을 것이다라는 경고 메시지에 주의 한다. 그럼 가보자: Firewall:~# nano -w /etc/default/shorewall지금은 그저 startup = 0을 startup = 1바꾸고 저장하고 나오자 Shorewall 설정 파일들은 두군데 장소에 저장된다: /etc/shorewall 은 모든 프로그램 설정파일들을 저장하고 /usr/share/shorewall을 지원 파일과 동작파일들을 저장한다. Shorewall의 데비안 패키지 버전에서는 /etc/shorewall은 비워있곤한다. 다행히 우리는 /usr/share/doc/shorewall/default-config에 기본적인 설정파일을 함께 제공하였다. 실제적으로 shorewall이 동작하기위한 이설정파일들을 사용하기만하면 되기 때문에 해야할 첫번째 일은 이것들을 /etc/shorewall에 복사하는 것 뿐이다. Firewall:~# cp /usr/share/doc/shorewall/default-config/* /etc/shorewall/그럼 우리의 /etc/sharewall디렉토리는 모든 설정파일들의 기본적인 복사본들로 채워질 것이다. 다음 우리는 방화벽을 기본적인 동작 명령에 따르게 하기 위해서 몇개 바꾸어 줄것이 있다. 나는 단지 방화벽이 동작하기 위해서 필요한 기본적인 설정들만 다룰 것이다. 각 단계에서 진짜로 무엇을 하는지 완벽히 이해하기 위해서 각 설정 파일의 문서들을 읽기 바란다. 먼저 우리의 네트워크 "zones"을 추가한다. Shorewall은 우리의 라우트된 네크워크의 다른 부분들을 정의하기 위해서 zones이라는 것을 사용한다. 우리의 간단한 설정은 두개이 zones를 사용할 것이다. Using libavformat and libavcode: An Update ¶from http://www.inb.uni-luebeck.de/~boehme/libavcodec_update.html Martin Bohme (boehme@inb.uni-luebeckREMOVETHIS.de) 2004년 7월 21일
갱신 (2005년 4월 26일): 한 독자가 Kanotix(Debian 파생물중의 하나인)와 Debian에서 예제 프로그램을 컴파일하는 하기 위해서 avcodec.h와 avformat.h를 위한 include 디렉토리는 다음과 같이 "ffmpeg"을 앞에 추가해주어야만한다.
#include <ffmpeg/avcodec.h> #include <ffmpeg/avformat.h> 또한, libdts 라이브러리는 프로그램을 컴파일할때 다음과 같이 추가해 주어야 한다.
g++ -o avcodec_sample.0.4.9 avcodec_sample.0.4.9.cpp -lavformat -lavcodec -ldts -lz 몇 달전에 나는 ffmpeg와 묶여져 있는 libavcodec과 libavformat 라이브러리의 사용에 대한 글을 섰다. 그 이후로 나는 수많은 조언들을 받았다. 그리고 ffmpeg(0.4.9-pre1)의 새로운 prelease 버전이 최근에 사용가능해 졌다. (비디오 파일 탐색, 새로운 파일 포멧, 그리고 비디오 프레임 읽기에 단순화된 인터페이스를 포함하는) 이러한 변화들은 한동안 CVS에서 이루어 졌다. 그러나 지금은 release에서 그들을 찾아 볼수 있는 첫번째 순간이다. (ffmpeg의 CVS버전을 습득하기위한 오랜 시간의 결과물을 공유한 것에 대해서 Silviu Minut에 감사드린다. - ffmpeg 정보와 데모 프로그램으로 채워진 그의 페이지는 여기에(http://www.cse.msu.edu/~minutsil/linux.html))이 글에서, 나는 단지 전버전의 release(0.4.8)과 새로운 버전사이의 다른부분에 대해서 언급할것이다. 그래서 만약 여러분들이 libavformat / libavcodec이 새롭다면 original article을 먼저 읽어 보기를 권한다.먼저, 새로운 release의 컴파일에 대한 것이다. 나의 컴퓨터(gcc 3.3.1 on SuSE)에서 소스파일 ffv1.c를 컴파일 하는 동안 내부 컴파일러 에러가 발생했다. 나는 이 특별한 버전의 gcc가 약간 유별나다고 의심한다. - OpenCV컴파일 할때도 나에게 똑같은 상황이 일어났다. - 그러나 아무튼 가장 빠른 방법은 optimization없이 이 파일을 컴파일 하는 것이다. 맨 처음 이 문제를 해결하기 위한 방법은 make를 실행하고, 빌드과정이 컴파일 에러를 발생할때 libavcodec 하부 디렉토리로 경로를 변경하고, (ffv1.c이 이곳에 있기때문에) 여러분의 터미날 윈도우로부터 ffv1.c를 컴파일 하기 위한 gcc 커멘드를 복사해 붙여 넣고, "-O3" 컴파일러 스위치를 제거한다. 그리고 나서 그 나머지 커맨드를 이용해서 gcc를 실행한다. 그 이후에 여러분들은 ffmpeg 디렉토리로 되돌아 가서 make를 다시 수행할 수 있고 아마도 완벽한 빌드를 얻을 수 있을 것이다.
What's New?
그럼 무엇이 새로워 진건가? 프로그래머의 입장에서 보면, 가장 큰 변화는 아마도 비디오 파일에서 개개의 비디오 프래임을 읽는 인터페이스가 단순화 된것이다. ffmpeg 0.4.8과 그 이전에서는 데이타는 av_read_packet()루틴을 통해서 비디오 파일로 부터 패킷으로 읽혀진다. 보통, 하나의 비디오 프레임을 위한 정보는 여러개의 패킷에 결쳐 영향을 미친다. 그리고 이 상황은 두 비디오 프래임사이의 경계가 두 패킷 사이의 중간에 올 수 있다는 사실로 인해 점점더 복잡하게 되어져 버린다. 감사하게도, ffmpeg 0.4.9는 av_read_frame() 이라고 하는 새로운 루틴을 제공한다. 그리고 그건 한 패킷에 있는 비디오 프레임에 대한 모든 데이타를 되돌려 준다. av_read_packet()을 통한 비디오 데이타를 읽는 이전의 방법은 여전히 지원되지만 그리 좋지 못하다. - 나는 좋은 변화라고 생각한다. 그래서 새로운 API를 이용해서 비디오 데이타를 억세스하는 방법을 살펴보자. 나의 original article에서 (이전의 0.4.8 API를 이용하는) 메인 디코드 루프는 다음과 같다.
while(GetNextFrame(pFormatCtx, pCodecCtx, videoStream, pFrame)) { img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height); // Process the video frame (save to disk etc.) DoSomethingWithTheImage(pFrameRGB); } GetNextFrame()은 하나의 비디오 프래임을 구성하는 모든 패킷들을 조합하는 과정을 다루는 보조적인 루틴이다. 새로운 API는 이것들을 우리가 메인 루프에서 직접 데이타를 실제로 읽고 디코드 할 수 있도록 하는 점으로 단순화 한다.
while(av_read_frame(pFormatCtx, &packet)>=0) { // Is this a packet from the video stream? if(packet.stream_index==videoStream) { // Decode video frame avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, packet.data, packet.size); // Did we get a video frame? if(frameFinished) { // Convert the image from its native format to RGB img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height); // Process the video frame (save to disk etc.) DoSomethingWithTheImage(pFrameRGB); } } // Free the packet that was allocated by av_read_frame av_free_packet(&packet); } 처음 볼때는 실제로 더 복잡하게 되어진 것처럼 보인다. - 그러나 이 각각의 코드는 GetNextFrame() 루틴에 숨겨진 것을 사용하는 부분을 수행하기 때문에 그렇다. (패킷이 비디오 스트림에 포함된다면, 프레임을 디코딩하고 패킷을 되돌려준다.) 결국, 우리는 GetNextFrame()을 완벽하게 제거할 수 있기때문에 좀더 쉽게 되어져 버렸다.
나는 이 새로운 API를 이용해서 데모 프로그램을 업데이트 했다. 단순히 라인 수를 비교해 보면(222라인의 이전버전 VS. 169라인의 새로운 버전) 새로운 API 고려할 만한 단순화되었다는 것을 보여준다.
0.4.9 release에서 또 하나의 중요한 추가사항은 비디오 파일에서 어떤 timestamp를 탐색하는 능력이다. 이것은 av_seek_frame()을 통해서 수행된다. 그리고 그건 새개의 인자를 필요로 한다. AVFormatContext의 포인터와 스트림 인덱스 그리고 탐색할 time stamp. 이 함수는 그럼 주어진 time stamp이전의 처음 key 프레임으로 탐색할 것이다. 이 모든것들은 문서화 되어 있다. - 나는 av_seek_frame()를 실제적으로 테스트할 기회를 아직 갖지 못했다. 그래서 또한 어떤 샘플 코드도 제공 할 수 없다. 만약 여러분이 av_seek_frame()을 성공적으로 사용했다면, 그에 관해서 들었으면 하는 바람이다.
Frame Grabbing (Video4Linux and IEEE1394)
Turo Tamaki씨는 libavformat / libavcodec을 이용해서 Video4Linux나 IEEE1394로 부터 프래임 그래빙하는 방법을 구현하는 약간의 샘플 코드들을 보내 왔다. Video4Linux에 대해선 av_open_input_file()으로의 분기는 다음과 같이 modify되어야 한다.
AVFormatParameters formatParams; AVInputFormat *iformat; formatParams.device = "/dev/video0"; formatParams.channel = 0; formatParams.standard = "ntsc"; formatParams.width = 640; formatParams.height = 480; formatParams.frame_rate = 29; formatParams.frame_rate_base = 1; filename = ""; iformat = av_find_input_format("video4linux"); av_open_input_file(&ffmpegFormatContext, filename, iformat, 0, &formatParams); IEEE1394를 위한 av_open_input_file()로의 분기는 다음과 같다.
AVFormatParameters formatParams; AVInputFormat *iformat; formatParams.device = "/dev/dv1394"; filename = ""; iformat = av_find_input_format("dv1394"); av_open_input_file(&ffmpegFormatContext, filename, iformat, 0, &formatParams); To be continued...
만약 내가 libavformat / libavcodec에 관한 흥미로운 정보를 추가적으로 만나게 된다면, 여기에 공표할 계획이다. 그래서 여러분들이 어떤 코멘트들을 있다면, 이 글의 맨위에 있는 주소로 나에게 접촉해 주기 바란다.
Standard disclaimer: I assume no liability for the correct functioning of the
code and techniques presented in this article.
Using libavformat and libavcodec ¶From http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html Martin Bohme (boehme@inb.uni-luebeckREMOVETHIS.de)
2004년 2월 18일
Update (2004/7/22) : 내가 최초로 제공한 코드가 메모리 누수현상을(av_free_packet()을 실행하지 않는) 가지고 있음을 발견했다. 나는 답례로 누수현상을 제거한 코드와 데모 프로그램으로 갱신했다.
libavformat과 libavcodec 라이브러리는 (ffmpeg에 부수적으로 따르는) 아주 다양한 비디오 파일 포멧을 다루는 가장 좋은 방법이다. 불행이도, 여러분의 프로그램에서 이 라이브러리들을 사용할때(적어도 나는 찾을 수가 없었다.) 실질적인 문서가 존재한지 않는다. 그리고 예제 프로그램들도 정말로 도움이 되지 않는다.
Update (2004/7/21) : ffmpeg(0.4.9-pre1)를 새로게 prelease했다. 나는 libavformat/libavcodec API의 변경사항을 기술한다. 이러한 상황으로 내가 최근 프로젝트에서 libavformat/libavcodec을 이용했을때 사용방법을 찾아내기 위해서 아주 많은 시행 착오를 거쳤다. 여기의 내용은 내가 배운 것들이다. - 부디 다른 이들이 똑같은 trial-and-error의 과정을 거치는 것으로 부터 도움이 되길 바란다. 또한 여러분들이 다운로드할 수 있는 작은 데모프로그램들도 있다. 이 코드는 ffmpeg 의 0.4.8 (내가 이글을 작성할 당시의 가장 최근버전인)버전에 포함된 libavformat/libavcodec으로 한 작업을 제공한다. 만약 여러분들이 이 코드를 break하는 이후의 버전을 찾는 다면, 나에게 알려주길 바란다.
이 문서에서 나는 단지 파일에서 비디오 스트림을 읽는 방법을 다룰것이다.: 오디오 스트림은 아주 많이 동일한 방법으로 동작한다. 그러나 나는 실질적으로 그것들을 사용하지은 않았다. 그래서 어떤 예제 코드들도 제공할 수 없다.
여러분들은 두개의 라이브러리, libformat과 libavcodec이 존재하는 하는지 의아해 한다. 많은 비디오 파일 포멧들은 (AVI가 본질적인 예로) 어떤 코덱이 오디오, 비디오 데이타를 엔코딩하는 데 사용되어야 하는지 일일이 열거하지 않는다. 그져 어떻게 오디오 비디오 스트림이 (혹은 간혹 몇몇 오디오 비디오 스트림) 하나의 파일로 합성되어야 하는지를 정의한다. 이것은 가끔 여러분들이 AVI파일을 열때, 왜 그림은 없고 소리만 나오게 되는 이유다. - 그건 올바른 비디오 코덱이 여러분의 시스템에 인스톨 되지 않았기 때문이다. 이와 같이, libavformat은 비디오 파일을 분석하고 포함된 스트림들을 구분하는 것을 다룬다. 그리고 libavcodec은 가공하지 않은 오디오 비디오 스트림들을 디코딩하는것을 다룬다.
Opening a Video File
처음 할 것들은 먼저 - 어떻게 비디오 파일을 여는지 살펴보고 포함된 스트림들을 얻어 보자. 우리가 처음 해야 할것은 libavformat과 libavcodec을 초기화 하는 것이다.
av_register_all(); 이것은 포멧과 코덱을 포함하는 파일이 열렸을 때 자동적으로 사용되어지게 하기 위해, 라이브러리에 연관된 모든 유용한 파일 포멧과 코덱들을 등록한다. 여러분들은 단지 av_register_all()을 한번 콜하기만 하면된다. 여러분의 startup 코드에 이것만으로도 충분히 훌룡하다. 만약 여러분들이 원한다면, 단지 어떤 특정 파일 포멧과 코덱들만 등록하는 것도 가능하다. 하지만 보통 여러분이 그렇게 해야할 이유는 없다.
다음은, 파일 열기
AVFormatContext *pFormatCtx; const char *filename="myvideo.mpg"; // Open video file if(av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)!=0) handle_error(); // Couldn't open file 마지막 세개의 파라미터들은 파일 포멧, 버퍼 사이즈, 그리고 포멧 파라미터들을 나타낸다. 그저 단순히 NULL이나 0으로 명기함으로써 libavformat이 포멧을 자동으로 인식하고 디폴트 버퍼 사이즈를 사용할 것을 요청한다. 여러분의 application을 위해선 handle_error()를 적절한 에러 핸들링 코드로 대체해라.
다음, 파일에 포함된 스트림에 관한 정보를 받기 원한다.
// Retrieve stream information if(av_find_stream_info(pFormatCtx)<0) handle_error(); // Couldn't find stream information 이것은 AVFormatContext의 streams 영역을 유용한 정보로 체운다. 디버깅을 돕기 위해서 이 정보를 표준 에러로 살펴볼것이다. 그러나 물론 여러분은 제품 application에서는 하지 말아야 한다.
dump_format(pFormatCtx, 0, filename, false); introduction에서 언급한 데로, 비디오 스트림만 다루고, 오디오 스트림은 다루지 않을 것이다. 명료하고 쉽게 하기 위해서 단지 맨 처음 찾게 되는 비디오 스트림을 사용한다.
int i, videoStream; AVCodecContext *pCodecCtx; // Find the first video stream videoStream=-1; for(i=0; i<pFormatCtx->nb_streams; i++) if(pFormatCtx->streams[i]->codec.codec_type==CODEC_TYPE_VIDEO) { videoStream=i; break; } if(videoStream==-1) handle_error(); // Didn't find a video stream // Get a pointer to the codec context for the video stream pCodecCtx=&pFormatCtx->streams[videoStream]->codec; 그럼, 여기서 우리는 비디오 스트림을 위한 코덱 context라 불리는 것의 포인터를 얻는다. 그러나 아직 실행할 코덱을 찾고 열어야 한다.
AVCodec *pCodec; // Find the decoder for the video stream pCodec=avcodec_find_decoder(pCodecCtx->codec_id); if(pCodec==NULL) handle_error(); // Codec not found // Inform the codec that we can handle truncated bitstreams -- i.e., // bitstreams where frame boundaries can fall in the middle of packets if(pCodec->capabilities & CODEC_CAP_TRUNCATED) pCodecCtx->flags|=CODEC_FLAG_TRUNCATED; // Open codec if(avcodec_open(pCodecCtx, pCodec)<0) handle_error(); // Could not open codec ("truncated bitstreams"에 대해서 알겠는가? 그럼 우리가 주지하다시피, 비디오 스트림에 있는 데이타는 패킷들로 나누어 진다. 비디오 프레임당 데이타의 양은 변할 수 있기때문에, 두 비디오 프레임들 사이의 경계는 패킷경계와 일치할 필요 없다. 여기서, 우리는 이 상황을 다룰수 있는 코덱을 이야기하고 있다.)
AVCodecContext 스트럭쳐에 저장된 정보중 중요한 한 부분은 비디오의 프레임 레이트이다. 정수가 아닌 프레임 레이트를 허용하기 위해서 (NTSC의 29.97fps와 같이), 레이트는 분수형태로 저장된다. (pCodecCtx->frame_rate인 분자와 pCodecCtx->frame_rate_base인 분모를 갖는) 서로 다른 비디오 파일들을 갖는 라이브러리를 테스트할때, 나는 어떤 코덱들은 (특히 ASF경우) 이 부분이 잘못 채워있는지에(fram_rate_base가 1000대신 1을 포함한다) 주의했다. 다음의 해킹한 수정사항들은 이것:
// Hack to correct wrong frame rates that seem to be generated by some // codecs if(pCodecCtx->frame_rate>1000 && pCodecCtx->frame_rate_base==1) pCodecCtx->frame_rate_base=1000; 버그가 어느날 수정될었을때 조차 해당 위치에 이 수정사항들을 남겨두어서 문제가 되지 말아야 한다. - 드물게 비디오가 1000fps이상의 프레임 레이트들 갖곤한다.
하나더 해야할 것이 남아 있다. 디코드된 영상들을 저장할 비디오 프레임을 확보해라.
AVFrame *pFrame; pFrame=avcodec_alloc_frame(); 그럼 이제 비디오 디코딩 작업을 시작하자.
Decoding Video Frames
내가 이미 언급한대로, 비디오 파일은 몇개의 오디오 비디오 스트림을 포함할 수 있다. 그리고 이 스트림은 각각 특정 사이즈의 패킷으로 나누어 진다. 우리가 할일은 이 패킷들을 하나씩 하나씩 libavformat을 이용해서 읽고, 우리가 원하던 비디오 스트림의 부분이 아닌 것들을 걸러 내고, 디코딩을 하기 위해서 그것들을 libavcodec으로 넘겨 주는 것이다. 이것을 하는데 있어서 우리는 두 프래임간의 경계가 패킷의 중간에 발생할 수 있다는 사실에 주의해야 할 것이다. 사운드가 복합된 것은? 다행이도, 우리는 루틴에 있는 다음 비디오 프레임을 넘겨주는 이 모든 과정들로 요약할 수 있다.
bool GetNextFrame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame *pFrame) { static AVPacket packet; static int bytesRemaining=0; static uint8_t *rawData; static bool fFirstTime=true; int bytesDecoded; int frameFinished; // First time we're called, set packet.data to NULL to indicate it // doesn't have to be freed if(fFirstTime) { fFirstTime=false; packet.data=NULL; } // Decode packets until we have decoded a complete frame while(true) { // Work on the current packet until we have decoded all of it while(bytesRemaining > 0) { // Decode the next chunk of data bytesDecoded=avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, rawData, bytesRemaining); // Was there an error? if(bytesDecoded < 0) { fprintf(stderr, "Error while decoding frame\n"); return false; } bytesRemaining-=bytesDecoded; rawData+=bytesDecoded; // Did we finish the current frame? Then we can return if(frameFinished) return true; } // Read the next packet, skipping all packets that aren't for this // stream do { // Free old packet if(packet.data!=NULL) av_free_packet(&packet); // Read new packet if(av_read_packet(pFormatCtx, &packet)<0) goto loop_exit; } while(packet.stream_index!=videoStream); bytesRemaining=packet.size; rawData=packet.data; } loop_exit: // Decode the rest of the last frame bytesDecoded=avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, rawData, bytesRemaining); // Free last packet if(packet.data!=NULL) av_free_packet(&packet); return frameFinished!=0; } 지금, 우리가 해야할 모든 것들은 루프문에 있다. (false를 되돌려 줄때까지 GetNextFrame()을 통해서) 그저 하나더 주의해야 할 것은: 대부분의 코덱들이 YUV 420 포멧의 영상들을 되돌려 준다. (한개의 luminance, 하나의 luminance 채널에 반개의 샘플을 갖는 두개의 chrominace 채널) 여러분은 비디오 데이타를 원하는 목적에 따라, RGB로 변환할 수 있다. (주의, 비록 당신이 원하던것들이 비디오 데이타를 디스플레이 하는 것이라면 할 필요 없지만, YUV-to-RGB와 하드웨어에서 스케일링작업을 하는 X11 Xvideo 확장을 살펴보라) 다행이도, libavcodec은 img_convert인 변환 루틴을 제공한다. 이것은 다양한 영상 포멧뿐만 아니라 YUV와 RGB사이의 변환을 한다. 비디오를 디코드하는 루프문은 다음과 같다.
while(GetNextFrame(pFormatCtx, pCodecCtx, videoStream, pFrame)) { img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height); // Process the video frame (save to disk etc.) DoSomethingWithTheImage(pFrameRGB); } RGB영상인 (AVFrame *)형태의 pFrameRGB은 다음과 같이 확보된다.
AVFrame *pFrameRGB; int numBytes; uint8_t *buffer; // Allocate an AVFrame structure pFrameRGB=avcodec_alloc_frame(); if(pFrameRGB==NULL) handle_error(); // Determine required buffer size and allocate buffer numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); buffer=new uint8_t[numBytes]; // Assign appropriate parts of buffer to image planes in pFrameRGB avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); Cleaning up
좋습니다. 우리는 비디오를 읽고 처리해서 지금 해야할 것은 스스로 clean up하는 것이다.
// Free the RGB image delete [] buffer; av_free(pFrameRGB); // Free the YUV frame av_free(pFrame); // Close the codec avcodec_close(pCodecCtx); // Close the video file av_close_input_file(pFormatCtx); 끝.
Sample Code
이 일련의 포함하는 샘플 어블리케이션은 여기에(http://www.inb.uni-luebeck.de/~boehme/avcodec_sample.cpp) 있다. 만약 당신이 어떤 추가적인 코멘트가 있다면, boehme@inb.uni-luebeckREMOVETHIS.de로 나에게 접촉해 달라. Standard disclaimer: I assume no liability for the correct functioning of the code and techniques presented in this article.
ASCII Expression under printf-format ¶\a "BELL" - i.e. a beep \b Backspace \f Form Feed (new page) \n New Line (line feed) \r Real carriage return \t Tab \v Vertical Tab \\ Backslash \' Single Quote \" Double Quote \? Question Mark Redhat Fedora Core 4 install without CDROM and Floppy ¶My system is windows XP on toshiba R100. Unfortunately PCMCIA-CDROM booting is not supported. In addition that Floppy installer is not metioned in Redhat. So, using GRUB boot manager, I construct HDD installer like below.
In menu.lst # This is a sample menu.lst file. You should make some changes to it. # Added items for installing GRUB [ which is on your DOS drive C: ] to MBR color black/cyan yellow/cyan timeout 60 default 0 title DOS/Win9x/Me/NT/2K/XP on (hd0,0) chainloader (hd0,0)+1 rootnoverify (hd0) title Redhat Fedora Core 4 install from CDROM (hd0,0) kernel (hd0,0)/ Distance between point and line ¶Let point (x, y) and line from (x1, y1) to (x2, y2)
then the distance is
D = Mysql "Error : Client does not support authentication protocol " ¶MySQL 5.0 uses an authentication protocol based on a password hashing algorithm that is incompatible with that used by older (pre-4.1) clients. If you upgrade the server from 4.1, attempts to connect to it with an older client may fail with the following message:
shell> mysqlClient does not support authentication protocol requested by server; consider upgrading MySQL client To solve this problem, you should use one of the following approaches:
Upgrade all client programs to use a 4.1.1 or newer client library.
When connecting to the server with a pre-4.1 client program, use an account that still has a pre-4.1-style password.
Reset the password to pre-4.1 style for each user that needs to use a pre-4.1 client program. This can be done using the SET PASSWORD statement and the OLD_PASSWORD() function:
mysql> SET PASSWORD FOR -> 'some_user'@'some_host' = OLD_PASSWORD('newpwd');Alternatively, use UPDATE and FLUSH PRIVILEGES: mysql> UPDATE mysql.user SET Password = OLD_PASSWORD('newpwd') -> WHERE Host = 'some_host' AND User = 'some_user'; mysql> FLUSH PRIVILEGES;Substitute the password you want to use for “newpwd” in the preceding examples. MySQL cannot tell you what the original password was, so you'll need to pick a new one. Gaussian Smoothing Filter ¶2 dimensional gaussian filter specified by standard deviation,
window size and scale.
such as
g(x, y) = exp(-(sqr(x/scale) + sqr(y/scale)) / sqr(sigma)) / (2 * PI * sqr(sigma));Propose two way routines that smooth with gaussian function created by lower bound and scale factor , or lower bound and window size. libiconv-1.9.1 (cross compile) ¶1. Extract the iconv library to your working directory.
% tar zxvf libiconv-1.9.1.tar.gz % cd libiconv-1.9.1 2. Configure the library for your environment.
% ./configure CC=arm-elf-gcc CFLAGS='-DHAVE_SYS_ERRLIST' --prefix=/install_dir --host=arm-elfonly for me % ./configure CC=arm-elf-gcc CFLAGS='-DHAVE_SYS_ERRLIST' --prefix=/opt/tools-install/arm-elf --host=arm-elf 3. Bulid package
% make % make install freetype-2.1.10 (cross compile) ¶1. Extract the freetype library to your working directory.
% tar zxvf freetype-2.1.10.tar.gz % cd freetype-2.1.10 2. Configure the library for your environment.
% ./configure --prefix=/install_dir --host=arm-elfOnly for me % ./configure --prefix=/opt/tools-install/arm-elf --host=arm-elf 3. Bulid package
% make % make install |
To criticize the incompetent is easy; it is more difficult to criticize the competent. |