patch_ffmpeg_x11grab.c
Go to the documentation of this file.
00001 /*
00002  * android video grab interface
00003  * Copyright (C) 2006 Jin Qian <osexp2003@gmail.com>
00004  */
00005 
00006 #include "config.h"
00007 #include "libavformat/internal.h"
00008 #include "libavutil/log.h"
00009 #include "libavutil/opt.h"
00010 #include "libavutil/parseutils.h"
00011 #include "libavutil/time.h"
00012 #include "libavutil/pixdesc.h"
00013 #include <time.h>
00014 #include "avdevice.h"
00015 #include <dlfcn.h>
00016 #include <unistd.h>
00017 #include <stdbool.h>
00018 
00019 struct ASC {
00020     void* priv_data;
00021     void* data;
00022     int size;
00023     int width;
00024     int height;
00025     char pixfmtName[32];
00026 };
00027 
00031 struct androidgrab {
00032     const AVClass *class;    
00034     double framerate;
00035 
00036     void* dlhandle;
00037     void (*asc_capture)(struct ASC*);
00038     struct ASC asc;
00039 
00040     int interval; //unit: us
00041     int64_t last_time;
00042 
00043     bool should_reuse_data;
00044 };
00045 
00056 static int
00057 androidgrab_read_header(AVFormatContext *s1)
00058 {
00059     struct androidgrab *agrab = s1->priv_data;
00060     AVStream *st = NULL;
00061 
00062     st = avformat_new_stream(s1, NULL);
00063     if (!st) return AVERROR(ENOMEM);
00064 
00065     avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
00066 
00067     agrab->interval = ((double)1000000)/agrab->framerate;
00068     agrab->dlhandle = dlopen(s1->filename, RTLD_NOW);
00069     if (!agrab->dlhandle) {
00070         av_log(s1, AV_LOG_ERROR, "dlopen err:%d(%s) %s\n", errno, strerror(errno), dlerror());
00071         return AVERROR(errno);
00072     }
00073 
00074     agrab->asc_capture = dlsym(agrab->dlhandle, "asc_capture");
00075     if (!agrab->asc_capture) {
00076         av_log(s1, AV_LOG_ERROR, "dlsym err:%d(%s)\n", errno, strerror(errno));
00077         return AVERROR(errno);
00078     }
00079 
00080     agrab->asc.priv_data = NULL;
00081     agrab->asc_capture(&agrab->asc);
00082     agrab->last_time = av_gettime();
00083 
00084     agrab->should_reuse_data = true;
00085 
00086     st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00087     st->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
00088     st->codec->width  = agrab->asc.width;
00089     st->codec->height = agrab->asc.height;
00090     st->codec->pix_fmt = av_get_pix_fmt(agrab->asc.pixfmtName);
00091     st->codec->time_base = av_d2q(1/agrab->framerate, 1000000);
00092     st->codec->bit_rate = agrab->asc.size * agrab->framerate * 8;
00093 
00094     return 0;
00095 }
00096 
00104 static int
00105 androidgrab_read_packet(AVFormatContext *s1, AVPacket *pkt)
00106 {
00107 //    char buf_log[512] = {0};
00108 //    sprintf(buf_log, "begin androidgrab_read_packet. pkt:%p\n", pkt);
00109 //    write(2, buf_log, strlen(buf_log));
00110 
00111     struct androidgrab *agrab = s1->priv_data;
00112     int64_t waitInterval;
00113 
00114     av_init_packet(pkt);
00115 
00116     if (agrab->should_reuse_data) {
00117         agrab->should_reuse_data = false;
00118     } else {
00119         //wait based on framerate
00120         waitInterval = av_gettime() - (agrab->last_time + agrab->interval);
00121         if (waitInterval > 0)
00122             usleep(waitInterval);
00123 
00124         agrab->asc_capture(&agrab->asc);
00125         agrab->last_time = av_gettime();
00126     }
00127 
00128     pkt->data = agrab->asc.data;
00129     pkt->size = agrab->asc.size;
00130     pkt->pts = agrab->last_time;
00131 
00132 //    sprintf(buf_log, "end   androidgrab_read_packet. pkt:%p pkt->data:%p\n", pkt, pkt->data);
00133 //    write(2, buf_log, strlen(buf_log));
00134 
00135     return agrab->asc.size;
00136 }
00137 
00144 static int
00145 androidgrab_read_close(AVFormatContext *s1)
00146 {
00147     return 0;
00148 }
00149 
00150 #define OFFSET(x) offsetof(struct androidgrab, x)
00151 #define DEC AV_OPT_FLAG_DECODING_PARAM
00152 static const AVOption options[] = {
00153     // { "framerate", "set video frame rate",  OFFSET(framerate),  AV_OPT_TYPE_DOUBLE, {.dbl = 4}, 0.1, 40,   DEC },
00154     { "width",     "horizontal size",   OFFSET(asc.width),  AV_OPT_TYPE_INT,    {.i64 = 0}, 0,   4096, DEC },
00155     { "height",    "vertical size",     OFFSET(asc.height), AV_OPT_TYPE_INT,    {.i64 = 0}, 0,   4096, DEC },
00156     { "framerate",    "max framerate",     OFFSET(framerate), AV_OPT_TYPE_DOUBLE,    {.dbl = 60}, 0,   60, DEC },
00157     { NULL },
00158 };
00159 
00160 static const AVClass android_class = {
00161     .class_name = "androidgrab indev",
00162     .item_name  = av_default_item_name,
00163     .option     = options,
00164     .version    = LIBAVUTIL_VERSION_INT,
00165 };
00166 
00168 AVInputFormat ff_x11grab_demuxer = {
00169     .name           = "androidgrab",
00170     .long_name      = NULL_IF_CONFIG_SMALL("androidgrab"),
00171     .priv_data_size = sizeof(struct androidgrab),
00172     .read_header    = androidgrab_read_header,
00173     .read_packet    = androidgrab_read_packet,
00174     .read_close     = androidgrab_read_close,
00175     .flags          = AVFMT_NOFILE,
00176     .priv_class     = &android_class,
00177 };


dji_ronin
Author(s):
autogenerated on Sat Jun 8 2019 20:15:31