<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:Calibri
}
--></style></head>
<body class='hmmessage'><div dir='ltr'>If you are thinking about commercial app, first, you must use x264 as an encoder, not ffmpeg. x264 is way optimized and the best encoder so far.<br>Secondly, you need to capture the screenshots in a thread because you can't capture fixed fps. with bitblt. Depending on the content of the desktop, you will sometimes have 10 fps, sometimes 20.<br><br><div><div id="SkyDrivePlaceholder"></div>> Date: Wed, 17 Apr 2013 15:28:12 -0700<br>> From: phuze9@gmail.com<br>> To: libav-user@ffmpeg.org<br>> Subject: Re: [Libav-user] Encoding a screenshot into a video using FFMPEG<br>> <br>> Thanks for your help, I discovered that my output video plays fine, but<br>> only in ffplay (in WMP/WMPClassic/VLC) it shows the gray distorted screen.<br>> I have made some changes to my code since the last update so I'll post what<br>> is working for me at the bottom of this. Can anyone think of a reason why<br>> the video would work well in ffplay and nothing else? Is there a setting<br>> that's causing this? I moved the screen capture code to another function,<br>> but it's similar with error checking for the getDIBits calls, which is<br>> where my earlier screenshot error was occurring, and also creating a<br>> COLORREF* rather than an RGBQUAD*.<br>> <br>> AVCodec* codec;<br>> AVCodecContext* c = NULL;<br>> uint8_t* outbuf;<br>> int i, out_size, outbuf_size;<br>> <br>> avcodec_register_all();<br>> <br>> printf("Video encoding\n");<br>> <br>> // Find the mpeg1 video encoder<br>> codec = avcodec_find_encoder(CODEC_ID_H264);<br>> if (!codec) {<br>> fprintf(stderr, "Codec not found\n");<br>> exit(1);<br>> }<br>> else printf("H264 codec found\n");<br>> <br>> c = avcodec_alloc_context3(codec);<br>> <br>> c->bit_rate = 400000;<br>> c->width = 1920; // resolution must be a multiple of two<br>> (1280x720),(1900x1080),(720x480)<br>> c->height = 1200;<br>> c->time_base.num = 1; // framerate numerator<br>> c->time_base.den = 25; // framerate denominator<br>> c->gop_size = 10; // emit one intra frame every ten frames<br>> c->max_b_frames = 1; // maximum number of b-frames between non b-frames<br>> //c->keyint_min = 1; // minimum GOP size<br>> //c->i_quant_factor = (float)0.71; // qscale factor between P and I frames<br>> //c->b_frame_strategy = 20;<br>> //c->qcompress = (float)0.6;<br>> //c->qmin = 20; // minimum quantizer<br>> //c->qmax = 51; // maximum quantizer<br>> //c->max_qdiff = 4; // maximum quantizer difference between frames<br>> //c->refs = 4; // number of reference frames<br>> //c->trellis = 1; // trellis RD Quantization<br>> c->pix_fmt = PIX_FMT_YUV420P;<br>> c->codec_id = CODEC_ID_H264;<br>> //c->codec_type = AVMEDIA_TYPE_VIDEO;<br>> <br>> // Open the encoder<br>> if (avcodec_open2(c, codec,NULL) < 0) {<br>> fprintf(stderr, "Could not open codec\n");<br>> exit(1);<br>> }<br>> else printf("H264 codec opened\n");<br>> <br>> outbuf_size = 100000 + c->width*c->height*(32>>3);//*(32>>3); // alloc<br>> image and output buffer<br>> outbuf = static_cast<uint8_t *>(malloc(outbuf_size));<br>> printf("Setting buffer size to: %d\n",outbuf_size);<br>> <br>> FILE* f = fopen("example.mpg","wb");<br>> if(!f) printf("x - Cannot open video file for writing\n");<br>> else printf("Opened video file for writing\n");<br>> <br>> // encode 5 seconds of video<br>> for(i=0;i<STREAM_FRAME_RATE*STREAM_DURATION;i++) {<br>> fflush(stdout);<br>> <br>> screenCap();<br>> <br>> <br>> int nbytes = avpicture_get_size(PIX_FMT_YUV420P, c->width, c->height);<br>> uint8_t* outbuffer = (uint8_t*)av_malloc(nbytes*sizeof(uint8_t));<br>> <br>> AVFrame* inpic = avcodec_alloc_frame();<br>> AVFrame* outpic = avcodec_alloc_frame();<br>> <br>> <br>> outpic->pts = (int64_t)((float)i * (1000.0/((float)(c->time_base.den))) *<br>> 90);<br>> avpicture_fill((AVPicture*)inpic, (uint8_t*)pPixels, PIX_FMT_RGB32,<br>> c->width, c->height); // Fill picture with image<br>> <br>> avpicture_fill((AVPicture*)outpic, outbuffer, PIX_FMT_YUV420P, c->width,<br>> c->height);<br>> av_image_alloc(outpic->data, outpic->linesize, c->width, c->height,<br>> c->pix_fmt, 1);<br>> <br>> inpic->data[0] += inpic->linesize[0]*(screenHeight-1); // Flipping frame<br>> inpic->linesize[0] = -inpic->linesize[0]; // Flipping frame<br>> <br>> struct SwsContext* fooContext = sws_getContext(screenWidth, screenHeight,<br>> PIX_FMT_RGB32, c->width, c->height, PIX_FMT_YUV420P, SWS_FAST_BILINEAR,<br>> NULL, NULL, NULL);<br>> <br>> sws_scale(fooContext, inpic->data, inpic->linesize, 0, c->height,<br>> outpic->data, outpic->linesize);<br>> <br>> // encode the image<br>> out_size = avcodec_encode_video(c, outbuf, outbuf_size, outpic);<br>> printf("Encoding frame %3d (size=%5d)\n", i, out_size);<br>> fwrite(outbuf, 1, out_size, f);<br>> delete [] pPixels;<br>> av_free(outbuffer);<br>> av_free(inpic);<br>> av_free(outpic);<br>> }<br>> <br>> // get the delayed frames<br>> for(; out_size; i++) {<br>> fflush(stdout);<br>> <br>> out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);<br>> printf("Writing frame %3d (size=%5d)\n", i, out_size);<br>> fwrite(outbuf, 1, out_size, f);<br>> }<br>> <br>> // add sequence end code to have a real mpeg file<br>> outbuf[0] = 0x00;<br>> outbuf[1] = 0x00;<br>> outbuf[2] = 0x01;<br>> outbuf[3] = 0xb7;<br>> fwrite(outbuf, 1, 4, f);<br>> fclose(f);<br>> <br>> avcodec_close(c);<br>> free(outbuf);<br>> av_free(c);<br>> printf("Closed codec and Freed\n");<br>> <br>> <br>> <br>> On Wed, Apr 17, 2013 at 3:50 AM, Steffen Ebersbach-2 [via libav-users] <<br>> ml-node+s943685n4657296h60@n4.nabble.com> wrote:<br>> <br>> > Hi<br>> ><br>> ><br>> > this is my code for making a video from a screenshot. I do not use the<br>> > hbitmap directly, but rather a gdi element. But i think this is not<br>> > necessary i do this or other reasons. One Idea, because in your last<br>> > picture the shell window is shown but the visual studio window is<br>> > missing, can be that the copy desktop / window function from windows<br>> > can't capy elements from directx and so on , only nativ stuff. This is<br>> > because in most remote control softwares, no video is transmitted.<br>> > I hope the codes help you.<br>> ><br>> > Steffen<br>> ><br>> > --------------------------------------------------<br>> > HWND window;<br>> > // get hwnd from your window / desktop / ...<br>> ><br>> > srcDC = GetDC(window);<br>> > tarDC = CreateCompatibleDC(srcDC);<br>> > m_pal = (HPALETTE) GetCurrentObject(srcDC, OBJ_PAL); //colors<br>> ><br>> > HBITMAP obmp, hbmp = CreateCompatibleBitmap(srcDC, pwidth , pheight);<br>> > obmp = (HBITMAP) SelectObject(tarDC, hbmp); //connect hbmp to DC<br>> ><br>> > res = SendMessage(window,WM_PRINT, (WPARAM)tarDC,(LPARAM) PRF_CLIENT |<br>> > ~PRF_ERASEBKGND); // Copy BMP<br>> > tarbmp = Gdiplus::Bitmap::FromHBITMAP(hbmp,m_pal);<br>> ><br>> > SelectObject(tarDC,obmp);<br>> > DeleteObject(hbmp);<br>> ><br>> ><br>> > //Stream and encoder<br>> > av_register_all();<br>> > avcodec_init();<br>> ><br>> > AVFormatContext *focontext;<br>> > AVStream *videostm;<br>> > AVCodec *videocodec;<br>> > AVCodecContext *videocontext;<br>> > AVFrame *aktframe;<br>> > uint8_t *framebuf1;<br>> > SwsContext *imgconvctx;<br>> ><br>> > //container<br>> > focontext = av_alloc_format_context();<br>> ><br>> > //videostream<br>> > videostm = av_new_stream(focontext,0);<br>> > // define your parameters here<br>> ><br>> > videocodec = avcodec_find_encoder(CODEC_ID_MPEG2VIDEO);<br>> > avcodec_open(videocontext, videocodec);<br>> ><br>> > focontext->video_codec_id = videocontext->codec_id;<br>> > av_set_parameters(focontext,0);<br>> ><br>> ><br>> > //frame<br>> > aktframe = avcodec_alloc_frame();<br>> > picsize = avpicture_get_size(PIX_FMT_YUV420P, width, height);<br>> > framebuf1 = (uint8_t*) av_malloc(picsize);<br>> > avpicture_fill( (AVPicture*)aktframe, framebuf1, PIX_FMT_YUV420P, width,<br>> > height);<br>> ><br>> > imgconvctx = sws_getContext(width, height ,PIX_FMT_BGR24 ,width,<br>> > height,PIX_FMT_YUV420P, SWS_BICUBIC , 0,0,0);<br>> ><br>> > //convert bmp<br>> > uint8_t *inbuffer;<br>> > Gdiplus::BitmapData inbmpdata;<br>> > Gdiplus::Rect cltrct(0,0,width,height);<br>> ><br>> > newbmp->LockBits(&cltrct, Gdiplus::ImageLockModeRead<br>> > ,PixelFormat24bppRGB , &inbmpdata);<br>> ><br>> > inbuffer = (uint8_t*) inbmpdata.Scan0;<br>> > AVFrame *inframe = 0;<br>> ><br>> > inframe = avcodec_alloc_frame();<br>> > avpicture_fill( (AVPicture*)inframe, inbuffer, PIX_FMT_BGR24, width,<br>> > height);<br>> > sws_scale(imgconvctx,inframe->data , inframe->linesize,0, height,<br>> > aktframe->data , aktframe->linesize);<br>> > int videobuf_size = videocontext->bit_rate *2;<br>> ><br>> > //open output<br>> > url_fopen(&focontext->pb,"file.mpg" , URL_WRONLY)<br>> > av_write_header(focontext);<br>> ><br>> > //encode and write frame<br>> > av_init_packet(&avpkt);<br>> > encsize = avcodec_encode_video(videocontext, videobuf ,videobuf_size,<br>> > aktframe);<br>> > avpkt.stream_index= videostm->index;<br>> > avpkt.data= videobuf;<br>> > avpkt.size= encsize;<br>> ><br>> > av_write_frame(focontext, &avpkt);<br>> ><br>> > // next frames<br>> > _______________________________________________<br>> > Libav-user mailing list<br>> > [hidden email] <http://user/SendEmail.jtp?type=node&node=4657296&i=0><br>> > http://ffmpeg.org/mailman/listinfo/libav-user<br>> ><br>> ><br>> > ------------------------------<br>> > If you reply to this email, your message will be added to the discussion<br>> > below:<br>> ><br>> > http://libav-users.943685.n4.nabble.com/Encoding-a-screenshot-into-a-video-using-FFMPEG-tp4657231p4657296.html<br>> > To unsubscribe from Encoding a screenshot into a video using FFMPEG, click<br>> > here<http://libav-users.943685.n4.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=4657231&code=cGh1emU5QGdtYWlsLmNvbXw0NjU3MjMxfC05NjM0NDkwOTQ=><br>> > .<br>> > NAML<http://libav-users.943685.n4.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml><br>> ><br>> <br>> <br>> <br>> <br>> --<br>> View this message in context: http://libav-users.943685.n4.nabble.com/Encoding-a-screenshot-into-a-video-using-FFMPEG-tp4657231p4657301.html<br>> Sent from the libav-users mailing list archive at Nabble.com.<br>> _______________________________________________<br>> Libav-user mailing list<br>> Libav-user@ffmpeg.org<br>> http://ffmpeg.org/mailman/listinfo/libav-user<br></div> </div></body>
</html>