วันพุธที่ 7 มีนาคม พ.ศ. 2555

Sungha Jung ทำให้ผมคิดได้

รู้จัก Sungha Jung กันมั้ยครับ??? ผมเชื่อว่า คนส่วนใหญ่ถ้าชอบเล่น ยูทูปหาคลิปนักดนตรีเจ๋งๆฟัง ต้องรู้จัก ไอหนุ่มไต้หวันคนนี้แน่นอน ด้วยฝีมือกีตาร์ระดับเมพใครได้ฟังเป็นอันต้องติดใจ ไอหนุ่มไต้หวันคนนี้เริ่มเล่นกีตาร์อัดคลิปลงยูทูปตั้งแต่ยังตัวกะเปี๊ยก ซึ่งเพลงแทบทั้งหมด ของ Sungha Jung ที่เล่นลงยูทูปจะเป็นบรรเลง ที่เล่นด้วยกีตาร์คลาสสิคทั้งหมด เอากันจริงๆครับ ฝีมือซะระดับนี่ อายุขนาดนี้เป็นผมคงไม่คิดทำอย่างอื่นแล้วครับ เล่นไปเรื่อยๆ ติดลมบนแล้ว พัฒนาฝีมือบ้างเล็กน้อบ ยังไงก็มีแฟนเพลงติดตามอยู่แล้ว

แต่!!! วันนี้ ไอหนุ่ม Sungha Jung โพสคลิปอันล่าสุดของเค้า ลงยูทูปครับ พร้อมกับ comment ลงไปในคลิปที่เค้าโพสเองว่า

‎"I just started the electric guitar 2 months ago. I think I have a lot to work on with it and I look forward to the journey!" - Sungha Jung
(ref:http://www.youtube.com/watch?v=cm8Ic2TwGjk&feature=share)

โอแม่เจ้า ใช่ครับ คลิปใหม่ของไอหนุ่มนี่ เป้นการเล่นกีตาร์ไฟฟ้าแทนกีตาร์คลาสสิคของถนัดของเค้า คือนับถือในตัวไอหนุ่มคนนี้เลยครับ ละหลังจากดูคลิปแล้วก็ มั่นใจได้เลยว่านี่จะไม่ใช่คลิปสุดท้ายที่เค้าเล่นกีต้าไฟฟ้า

ดูแล้วคิดถึงคำว่าคนเราต้องไม่หยุดพัฒนาตัวเองจริงๆครับ ทุกช่วงเวลาที่ยังมีอยู่คือการเรียนรู้ การเรียนรู้และรู้ว่าเรารักที่จะทำอะไรนั่นล่ะครับ คือการทำให้ชีวิตนี้มีคุณค่า

ผมเห็นคนหลายๆคนเมื่อชีวิตมาถึงจุดๆนึงที่คิดว่าเราพอแล้ว สบายแล้วหรือปลงแล้ว กูไม่ทำแม่งแล้ว เราก็ จะเริ่มใช้ชีวิต ไปอย่างไร้ค่า ผ่านไปวันๆ โดยไม่คิดว่า เออ แม่ง คนเรามีชีวิตเดียวนะเว้ย เชื่อเรื่องเกิดใหม่หรอ ถ้าตายแล้วดับสูญไปเลยอะ ไม่เสียดายแย่หรอฟระ

ต้องขอบคุณ Sungha Jung มากครับที่ทำให้ผมคิดอะไรได้ ถ้าวันนึง ผมได้ออกรายการพี่ต๋อย ว่าจุดเปลี่ยนในชีวิตของคุณคืออะไร ผมก็จะตอบว่า คือการได้ดูคลิปที่ Sungha Jung เริ่มเล่นกีตาร์ไฟฟ้านี่ล่ะครับ!!!

วันอาทิตย์ที่ 15 มกราคม พ.ศ. 2555

welcome 2012

แป๊ป ๆล่วงเข้ามา ปี 2012 ปีนี้ ชงสะด้วย ครับ และน่าจะเป็นปีที่เรา เริ่มพ้นวัยรุ่น (จะสามสิบ) ฮ่าๆ

blog นี่ อย่างที่เคยบอก สร้างไว้นานมาๆ ไม่ค่อยจะเข้ามาเขียน เพราะส่วนตัวเป็นคนขี้เกียจ ต้องว่างมาก และไม่มีอะไรทำสุดๆ จีงจะเข้ามา ปีนี้ อยากจะเขียนให้มากขึ้น เพราะคิดว่า เราเจออะไร ที่น่าสนใจๆ มา เยอะเหมือนกัน เลย อยากจะเก็บไว้ให้คนอื่น ได้มาอ่านด้วย

พูดถึง สิ่งที่อยากทำในปีนี้ก็มีเยอะแยะมากมาย ตั้งแต่ งานวิจัย ที่ทำอยู่ที่จุฬา ก็อยากให้เวลา กับมันมากขึ้น ส่วนงานประจำ ก็เริ่มเข้าที่เข้าทางแล้ว งานฟรีแลนซ์ที่ทำมาเกือบสองปี ปีนี้ ก็แพลนว่าจะเลิกทำแล้วมาทำอะไร กับเพื่อน กับฝูง กับตัวเอง มั่ง น่าจะ ทำให้ชีวิต มีความสุขมากขึ้น

สุดท้ายนี้ ขอ บันทึกไว้ในโพสต์นี้ละกันว่าจะเขียนบล๊อกตัวเองให้มากขึ้นครับ เพราะเดี๋ยวนี้มีแอร์การ์ดแล้วด้วย อัพได้ทุกที่ (ที่มีสัญญาณ) :)

วันพฤหัสบดีที่ 28 เมษายน พ.ศ. 2554

Writing "C" code to encode and decode H.264 by using libavcodec

This example implement base on api-example source code. It will show you how to write "C" code to encode raw data (qcif) to h264 and decoded it to yuv.

Part of the main code is shown below.

int main(int argc, char **argv)
{

/* must be called before using avcodec lib */
avcodec_init();

/* register all the codecs */
avcodec_register_all();

h264_encode_decode("Foreman.qcif","Decoded.yuv");

return 0;
}


We start with registering and initialize codec. And then we call function h264_encode_decode(), this function will encode input file ("Foreman.qcif") to h.264 and then decode it to yuv file ("Decoded.yuv").

I will divide h264_encode_decode function into 5 steps.

1. Declare variable that use in decode and encode.

AVCodec *codecEncode, *codecDecode;
AVCodecContext *ctxEncode= NULL, *ctxDecode = NULL;

FILE *fin, *fout;
AVFrame *pictureEncoded, *pictureDecoded;

uint8_t *encoderOut, *picEncodeBuf;
int encoderOutSize, decoderOutSize;
int pic_size;

AVPacket avpkt;
int got_picture, len;

const int clip_width = 176;
const int clip_height = 144;

int frame = 0;
uint8_t *decodedOut;



2. Initial codec/picture structure for decoder.

codecDecode = avcodec_find_decoder(CODEC_ID_H264);
if (!codecDecode) {
fprintf(stderr, "codec not found\n");
exit(1);
}

ctxDecode= avcodec_alloc_context();
avcodec_get_context_defaults(ctxDecode);
ctxDecode->flags2 |= CODEC_FLAG2_FAST;
ctxDecode->pix_fmt = PIX_FMT_YUV420P;
ctxDecode->width = clip_width;
ctxDecode->height = clip_height;
ctxDecode->dsp_mask = (FF_MM_MMX | FF_MM_MMXEXT | FF_MM_SSE);

if (avcodec_open(ctxDecode, codecDecode) < 0) {
fprintf(stderr, "could not open codec\n");
exit(1);
}

pictureDecoded= avcodec_alloc_frame();
avcodec_get_frame_defaults(pictureDecoded);
pic_size = avpicture_get_size(PIX_FMT_YUV420P, clip_width, clip_height);

decodedOut = (uint8_t *)malloc(pic_size);
fout = fopen(fileout, "wb");
if (!fout) {
fprintf(stderr, "could not open %s\n", fileout);
exit(1);
}



3. Initial codec/picture for encoder.

codecEncode = avcodec_find_encoder(CODEC_ID_H264);
if (!codecEncode) {
printf("codec not found\n");
exit(1);
}

ctxEncode= avcodec_alloc_context();
ctxEncode->coder_type = 0; // coder = 1
ctxEncode->flags|=CODEC_FLAG_LOOP_FILTER; // flags=+loop
ctxEncode->me_cmp|= 1; // cmp=+chroma, where CHROMA = 1
ctxEncode->partitions|=X264_PART_I8X8+X264_PART_I4X4+X264_PART_P8X8+X264_PART_B8X8; // partitions=+parti8x8+parti4x4+partp8x8+partb8x8
ctxEncode->me_method=ME_HEX; // me_method=hex
ctxEncode->me_subpel_quality = 0; // subq=7
ctxEncode->me_range = 16; // me_range=16
ctxEncode->gop_size = 30*3; // g=250
ctxEncode->keyint_min = 30; // keyint_min=25
ctxEncode->scenechange_threshold = 40; // sc_threshold=40
ctxEncode->i_quant_factor = 0.71; // i_qfactor=0.71
ctxEncode->b_frame_strategy = 1; // b_strategy=1
ctxEncode->qcompress = 0.6; // qcomp=0.6
ctxEncode->qmin = 0; // qmin=10
ctxEncode->qmax = 69; // qmax=51
ctxEncode->max_qdiff = 4; // qdiff=4
ctxEncode->max_b_frames = 3; // bf=3
ctxEncode->refs = 3; // refs=3
ctxEncode->directpred = 1; // directpred=1
ctxEncode->trellis = 1; // trellis=1
ctxEncode->flags2|=CODEC_FLAG2_FASTPSKIP; // flags2=+bpyramid+mixed_refs+wpred+dct8x8+fastpskip
ctxEncode->weighted_p_pred = 0; // wpredp=2
ctxEncode->bit_rate = 32000;
ctxEncode->width = clip_width;
ctxEncode->height = clip_height;
ctxEncode->time_base.num = 1;
ctxEncode->time_base.den = 30;
ctxEncode->pix_fmt = PIX_FMT_YUV420P;
ctxEncode->dsp_mask = (FF_MM_MMX | FF_MM_MMXEXT | FF_MM_SSE);
ctxEncode->rc_lookahead = 0;
ctxEncode->max_b_frames = 0;
ctxEncode->b_frame_strategy =1;
ctxEncode->chromaoffset = 0;
ctxEncode->thread_count =1;
ctxEncode->bit_rate = (int)(128000.f * 0.80f);
ctxEncode->bit_rate_tolerance = (int) (128000.f * 0.20f);
ctxEncode->gop_size = 30*3; // Each 3 seconds

/* open codec for encoder*/
if (avcodec_open(ctxEncode, codecEncode) < 0) {
printf("could not open codec\n");
exit(1);
}

//open file to read
fin = fopen(filein, "rb");
if (!fin) {
printf("could not open %s\n", filein);
exit(1);
}

/* alloc image and output buffer for encoder*/
pictureEncoded= avcodec_alloc_frame();
avcodec_get_frame_defaults(pictureEncoded);

//encoderOutSize = 100000;
encoderOut = (uint8_t *)malloc(100000);
//int size = ctxEncode->width * ctxEncode->height;
picEncodeBuf = (uint8_t *)malloc(3*pic_size/2); /* size for YUV 420 */
pictureEncoded->data[0] = picEncodeBuf;
pictureEncoded->data[1] = pictureEncoded->data[0] + pic_size;
pictureEncoded->data[2] = pictureEncoded->data[1] + pic_size / 4;
pictureEncoded->linesize[0] = ctxEncode->width;
pictureEncoded->linesize[1] = ctxEncode->width / 2;
pictureEncoded->linesize[2] = ctxEncode->width / 2;


4. Read data from input file and encode it by using avcodec_encode_video, encoded data will send to decode to yuv format by using avcodec_decode_video2. Decoded data will be written to decoded.yuv file.

//encode and decode loop
for(int i=0;i<30;i++)
{
fflush(stdout);
//read qcif 1 frame to buufer
fread(pictureEncoded->data[0],ctxEncode->width * ctxEncode->height, 1, fin);
fread(pictureEncoded->data[1],ctxEncode->width * ctxEncode->height/4, 1, fin);
fread(pictureEncoded->data[2],ctxEncode->width * ctxEncode->height/4, 1, fin);
pictureEncoded->pts = AV_NOPTS_VALUE;

/* encode frame */
encoderOutSize = avcodec_encode_video(ctxEncode, encoderOut, 100000, pictureEncoded);
printf("encoding frame %3d (size=%5d)\n", i, encoderOutSize);
if(encoderOutSize <= 0)
continue;

//send encoderOut to decoder
avpkt.size = encoderOutSize;
avpkt.data = encoderOut;
//decode frame
len = avcodec_decode_video2(ctxDecode, pictureDecoded, &got_picture, &avpkt);
if (len < 0) {
printf("Error while decoding frame %d\n", frame);
exit(1);
}
if (got_picture) {
printf("len = %d saving frame %3d\n", len, frame);
fflush(stdout);

avpicture_layout((AVPicture *)pictureDecoded, ctxDecode->pix_fmt
, clip_width, clip_height, decodedOut, pic_size);
fwrite(decodedOut, pic_size, 1, fout);
frame++;
}
}


5. Free allocated memory and close file pointer.

fclose(fout);
fclose(fin);

avcodec_close(ctxEncode);
avcodec_close(ctxDecode);
av_free(ctxEncode);
av_free(ctxDecode);
av_free(pictureEncoded);
av_free(pictureDecoded);


This implementation will show you how to use libavcodec to encode and decode h264 correctly. hope it will help you to understand encode/decode scenario when using libavcodec.

:)

Compile/build api-example of libavcodec on window with visual c++ 2008.

This post will show, how to compile and build api-exampl.c with visual c++ 2008.

api-example.c is contained in libavcodec folder, this file show you how to use api of libavcodec.
If you can compile it on window you will get idea to use it on your window application.

An example assume, you already have dll, lib and necessary include file on your machine.

1.Create VS C++ with console application project and add api-example.cpp (change file extension form .c to .cpp) to your project.

2.At this step if you compile you will get error message about cannot open include file. you need to set include files path of your visual studio.



- D:\TSL_Project\include; contain inttypes.h and stdint.h these files aren't in VS2008.
- C:\msys\1.0\local\include; contain libavcodec and other necessary include files.

3.Modify your api-example code by
- put extern "C" keywords between include header file of ffmpeg because it come form C coding style
- define "__STDC_CONSTANT_MACROS" this will remove error about "error C3861: 'INT64_C': identifier not found"



4.At this step if you compile code you will get 2 types of error first is cannot convert pointer and second is "snprintf': identifier not found". You need to fix it by.

- For pointer type you can convert it manually by yourself.
- For snprintf you need to use _snprintf instead.

5.At this step you can compile without error, BUT when you build project you will get a error like "unresolved external symbol" , because you still not set linker to your project.

- Add lib directory to VS2008



- Add lib to linker input



6.After add linker you can completely build your project BUT!!! it still not complete process to run your application,

You can build your project without error but you cannot launch your application because you don't have ".dll" in your directory so let's copy it all and paste to your directory and it will work :) .

Simple software for playing/encoding qcif and yuv.

Last post I talk about yuv, qcif player.

So I wanna show my software that I wrote it longtime ago. This software use for playing and encoding h.264. Encoder of this software is very old JM h.264 version.

This software develop by c++builder6 the easy platform to make GUI by C++ language.

The main window after open qcif file is look like this.
















You can play sequence in sequence player of open more clip.
And then if you want to encode it you can set encode parameter by using h.264 option like this.

















And then you can encode by select File->start encoding . Software will encode your sequence to h.264 format. And save it to .264 format and .yuv that already reconstruct.

















This software is not good design and coding but if you wanna demonstrate encode/decode h.264 and wanna see input/output of sequence with simple way you can use it.

p.s. you can email to me if wanna try this software :) .

How to encode and decode h.264 by using ffmpeg.

Today I take time to demonstrate encode and decode process with ffmpeg/x264.

first I will show about how to encode h.264 by ffmpeg and then I will show decode.
This demonstration work on windows7 32bits.

Encode h.264
1.We need to prepare environment like this.
- ffmpeg.exe and its dll.
- libx264
* You can get ffmpeg and libx264 library by download from website or you can get its source code and make install to msys. I will talk about how to build ffmpeg on window on the next post.

2.go to directory that contain your ffmpeg lib and type this command on your console.

ffmpeg.exe -s qcif -i Foreman.qcif -r 25 -an -pass 1 -vcodec libx264 -fpre libx264-lossless_fast.ffpreset -b 32000 -threads 0 test.mp4

parameter meaning will describe here.

-s qcif ; tell ffmpeg that we will encode input yuv video with qcif(176*144) size.

-i Foreman.qcif ; define input sequence I use the test classic test sequence that name foreman.qcif , I think you can get it on google.

-r 25; set frame rate

-an; disable audio we will encode only video data

-pass 1; use 1 pass video coding

-vcodec libx264; use libx264 for codec

-fpre libx264-lossless_fast.ffpreset; define encoding parameter for h.264 that contain in ffpreset file.

-b 32000; set bit rate as 32kbps.

-threads 0; set thread for encoding to zero.

test.mp4; define output file.

And after run this command encoded sequence will be created to test.mp4 and console log will shown like this.









you can play test.mp4 to see the result clip by using player that contain h.264 codec.


Decode h.264

decode process is easier, it just type a few command line to ffmpeg like this.

ffmpeg -i test.mp4 decode_out.yuv

-i test.mp4 ; define input sequence to decode.
- decode_out.yuv; define output sequence in format of yuv.

And the output that show on console will look like this.













decode_out.yuv can open by using yuv player.

That's all for this post, next post I will show about how to write code in c++ to encode/decode h.264 by using libavcodec of ffmpeg.

วันพุธที่ 16 มีนาคม พ.ศ. 2554