[FFmpeg-devel] x11 output device for libavdevice

Moguillansky, Jeff Jeff.Moguillansky at am.sony.com
Thu Apr 11 03:05:45 CEST 2013


Hi,
Let me know if this is better.
Here's a patch file.  
I added error handling, fixed the includes, and got rid of the for loop.  I'm not sure how to modify configure script (I just modified the generated makefiles)?

Thanks,
Jeff
________________________________________
From: ffmpeg-devel-bounces at ffmpeg.org [ffmpeg-devel-bounces at ffmpeg.org] on behalf of Paul B Mahol [onemda at gmail.com]
Sent: Wednesday, April 10, 2013 4:30 PM
To: FFmpeg development discussions and patches
Subject: Re: [FFmpeg-devel] x11 output device for libavdevice

On 4/10/13, Moguillansky, Jeff <Jeff.Moguillansky at am.sony.com> wrote:
> Hello,
> I really like the libavdevice code.  I implemented an X11 output device for
> libavdevice.  I would like to request if it's possible to add this to the
> main branch?  It uses XVideo extension for hardware acceleration and it
> supports window resizing.
>
> To use (with video and audio output):
> ffmpeg -i <input file> -f x11 "Output" -f alsa "default"
>
> Here's my code:

First normal way to send code is via patch.

>
> libavdevice/x11.c:
>
> /*
>  * Copyright (c) 2011 Jeff Moguillansky
>  *
>  * This file is part of FFmpeg.
>  *
>  * FFmpeg is free software; you can redistribute it and/or
>  * modify it under the terms of the GNU Lesser General Public
>  * License as published by the Free Software Foundation; either
>  * version 2.1 of the License, or (at your option) any later version.
>  *
>  * FFmpeg is distributed in the hope that it will be useful,
>  * but WITHOUT ANY WARRANTY; without even the implied warranty of
>  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>  * Lesser General Public License for more details.
>  *
>  * You should have received a copy of the GNU Lesser General Public
>  * License along with FFmpeg; if not, write to the Free Software
>  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
> USA
>  */
>
> #include "libavutil/avstring.h"
> #include "libavutil/opt.h"
> #include "libavutil/parseutils.h"
> #include "libavutil/pixdesc.h"
> #include "avdevice.h"
> #include <X11/Xlib.h>
> #include <X11/extensions/Xv.h>
> #include <X11/extensions/Xvlib.h>
> #include <sys/shm.h>

Wrong order of headers. <> ones goes first.

>
> typedef struct {
>       GC gc; Window window; Display* dpy; XvImage* yuv_image[1]; XShmSegmentInfo
> yuv_shminfo[1];
>       int xv_port, width, height;
> } X11Data;
>
> typedef struct {
>     AVClass *class;
>     char *window_title;
>     X11Data *data;
> } X11Context;
>
> #define OFFSET(x) offsetof(X11Context,x)
>
> static int x11_write_header(AVFormatContext *s) {

If you looked at other files in libavdevice, you would notice they do
not use such coding style.

>       X11Context *x11 = s->priv_data;
>       X11Data *data = (X11Data*)calloc(1,sizeof(X11Data));
>       unsigned int p_num_adaptors;
>       int j;
>       XvAdaptorInfo *ai;
>       AVCodecContext *pCodecCtx = s->streams[0]->codec;
>       x11->data = data;
>       if (!x11->window_title) x11->window_title = av_strdup("");
>       data->width = pCodecCtx->width; data->height = pCodecCtx->height;
>       data->dpy = XOpenDisplay(NULL);
>       data->window = XCreateSimpleWindow(data->dpy,
> DefaultRootWindow(data->dpy),0, 0,data->width,data->height,0,0,0);
>       XStoreName(data->dpy, data->window, x11->window_title);
>       XMapWindow(data->dpy, data->window);
>       XvQueryAdaptors(data->dpy, DefaultRootWindow(data->dpy),&p_num_adaptors,
> &ai);
>       data->xv_port = ai[0].base_id;
>       data->gc = XCreateGC(data->dpy, data->window, 0, 0);

Can any of those fail? If yes, it will segv on next call which is far
from being robust.

>       for (j = 0; j<1; j++) {

What is point of this loop?

>               data->yuv_image[j] = XvShmCreateImage(data->dpy, data->xv_port+j,
> ('I'|('4'<<8)|('2'<<16)|'0'<<24) , 0, data->width, data->height,

Probably other format can be queried and supported to. Beside there is
nicer way to write I420.

> &data->yuv_shminfo[j]);
>               data->yuv_shminfo[j].shmid = shmget(IPC_PRIVATE,
> data->yuv_image[j]->data_size, IPC_CREAT | 0777);
>               data->yuv_image[j]->data = (char*)shmat(data->yuv_shminfo[j].shmid, 0, 0);
> data->yuv_shminfo[j].shmaddr = data->yuv_image[j]->data;
>               data->yuv_shminfo[j].readOnly = False;
>       }
>       XShmAttach(data->dpy, &data->yuv_shminfo[0]);
>       return 0;
> }
>
> static int x11_write_packet(AVFormatContext *s, AVPacket *pkt) {
>       X11Context *x11 = s->priv_data;
>       X11Data *data = x11->data;
>       XvImage *img = data->yuv_image[0];
>       int     y, h = img->height / 2;
>       XWindowAttributes attr;
>       AVPicture pict;
>       AVCodecContext *pCodecCtx = s->streams[0]->codec;
>       avpicture_fill(&pict, pkt->data, pCodecCtx->pix_fmt, pCodecCtx->width,
> pCodecCtx->height);
>       for(y = 0; y < img->height; y++) {
>               memcpy(&img->data[img->offsets[0] + (y * img->pitches[0])],
> &pict.data[0][y * pict.linesize[0]], img->pitches[0]);
>       }
>       for(y = 0; y < h; ++y) {
>               memcpy(&img->data[img->offsets[1] + (y * img->pitches[1])],
> &pict.data[1][y * pict.linesize[1]], img->pitches[1]);
>               memcpy(&img->data[img->offsets[2] + (y * img->pitches[2])],&pict.data[2][y
> * pict.linesize[2]], img->pitches[2]);
>       }
>       XGetWindowAttributes(data->dpy, data->window,&attr);
>       XvShmPutImage(data->dpy, data->xv_port, data->window, data->gc,
> data->yuv_image[0],0, 0, data->width, data->height,0, 0,
> attr.width,attr.height, True);
>       XSync(data->dpy,True);
>       return 0;
> }
>
> static int x11_write_trailer(AVFormatContext *s) {
>       X11Context *x11 = s->priv_data;
>       X11Data *data = x11->data;
>       int j;
>       av_freep(&x11->window_title);
>       XShmDetach(data->dpy,&data->yuv_shminfo[0]);
>       for (j = 0; j<1; j++) {
>               shmdt(data->yuv_image[j]->data);
>               XFree(data->yuv_image[j]);
>       }
>       XCloseDisplay(data->dpy);
>
>       return 0;
> }
>
> static const AVOption options[] = {
>     { "window_title", "set X11 window title", OFFSET(window_title),
> AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM },
>       { NULL },
> };
>
> static const AVClass x11_class = {
>     .class_name = "x11 outdev",
>     .item_name  = av_default_item_name,
>     .option     = options,
>     .version    = LIBAVUTIL_VERSION_INT,
> };
>
> AVOutputFormat ff_x11_muxer = {
>     .name           = "x11",
>     .long_name      = NULL_IF_CONFIG_SMALL("x11 output device"),
>     .priv_data_size = sizeof(X11Context),
>     .audio_codec    = AV_CODEC_ID_NONE,
>     .video_codec    = AV_CODEC_ID_RAWVIDEO,
>     .write_header   = x11_write_header,
>     .write_packet   = x11_write_packet,
>     .write_trailer  = x11_write_trailer,
>     .flags          = AVFMT_NOFILE | AVFMT_VARIABLE_FPS |
> AVFMT_NOTIMESTAMPS,
>     .priv_class     = &x11_class,
> };
>
>
>
>
> ....
> here's the other modifications:
> libavdevice/alldevices.c:
> void avdevice_register_all(void) {
>   ...
> REGISTER_OUTDEV (X11, x11);
>   ...
> }
>
> libavdevice/Makefile:
> ...
> OBJS-$(CONFIG_X11_OUTDEV)                += x11.o
>
>
> ffmpeg/config.mak:
> EXTRALIBS=... -lX11 -lXv ...
>
> ffmpeg/config.h:
> ...
> #define CONFIG_X11_OUTDEV 1
>
>
>
>
> Thanks,
> Jeff

Please tell us if you do NOT plan to work on above mentioned code issues.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel at ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: x11_output.patch
Type: text/x-patch
Size: 7276 bytes
Desc: x11_output.patch
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130411/5996a6ca/attachment.bin>


More information about the ffmpeg-devel mailing list