1
/* $Id: ffmpeg_dev.c 3893 2011-12-01 10:49:07Z ming $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
/* Video device with ffmpeg backend, currently only capture devices are
24
* - no device enumeration (ffmpeg limitation), so this uses "host API" enum
26
* - need stricter filter on "host API" enum, currently audio capture devs are
28
* - no format enumeration, currently hardcoded to PJMEDIA_FORMAT_RGB24 only
29
* - tested on Vista only (vfw backend) with virtual cam
30
* - vfw backend produce bottom up pictures
31
* - using VS IDE, this cannot run under debugger!
34
#include <pjmedia-videodev/videodev_imp.h>
35
#include <pj/assert.h>
38
#include <pj/unicode.h>
41
#if defined(PJMEDIA_VIDEO_DEV_HAS_FFMPEG) && PJMEDIA_VIDEO_DEV_HAS_FFMPEG != 0
44
#define THIS_FILE "ffmpeg.c"
46
#include "../pjmedia/ffmpeg_util.h"
47
#include <libavdevice/avdevice.h>
48
#include <libavformat/avformat.h>
52
typedef struct ffmpeg_dev_info
54
pjmedia_vid_dev_info base;
55
AVInputFormat *host_api;
56
const char *def_devname;
60
typedef struct ffmpeg_factory
62
pjmedia_vid_dev_factory base;
67
ffmpeg_dev_info dev_info[MAX_DEV_CNT];
71
typedef struct ffmpeg_stream
73
pjmedia_vid_dev_stream base;
74
ffmpeg_factory *factory;
76
pjmedia_vid_dev_param param;
77
AVFormatContext *ff_fmt_ctx;
82
static pj_status_t ffmpeg_factory_init(pjmedia_vid_dev_factory *f);
83
static pj_status_t ffmpeg_factory_destroy(pjmedia_vid_dev_factory *f);
84
static pj_status_t ffmpeg_factory_refresh(pjmedia_vid_dev_factory *f);
85
static unsigned ffmpeg_factory_get_dev_count(pjmedia_vid_dev_factory *f);
86
static pj_status_t ffmpeg_factory_get_dev_info(pjmedia_vid_dev_factory *f,
88
pjmedia_vid_dev_info *info);
89
static pj_status_t ffmpeg_factory_default_param(pj_pool_t *pool,
90
pjmedia_vid_dev_factory *f,
92
pjmedia_vid_dev_param *param);
93
static pj_status_t ffmpeg_factory_create_stream(
94
pjmedia_vid_dev_factory *f,
95
pjmedia_vid_dev_param *param,
96
const pjmedia_vid_dev_cb *cb,
98
pjmedia_vid_dev_stream **p_vid_strm);
100
static pj_status_t ffmpeg_stream_get_param(pjmedia_vid_dev_stream *strm,
101
pjmedia_vid_dev_param *param);
102
static pj_status_t ffmpeg_stream_get_cap(pjmedia_vid_dev_stream *strm,
103
pjmedia_vid_dev_cap cap,
105
static pj_status_t ffmpeg_stream_set_cap(pjmedia_vid_dev_stream *strm,
106
pjmedia_vid_dev_cap cap,
108
static pj_status_t ffmpeg_stream_start(pjmedia_vid_dev_stream *strm);
109
static pj_status_t ffmpeg_stream_get_frame(pjmedia_vid_dev_stream *s,
110
pjmedia_frame *frame);
111
static pj_status_t ffmpeg_stream_stop(pjmedia_vid_dev_stream *strm);
112
static pj_status_t ffmpeg_stream_destroy(pjmedia_vid_dev_stream *strm);
115
static pjmedia_vid_dev_factory_op factory_op =
117
&ffmpeg_factory_init,
118
&ffmpeg_factory_destroy,
119
&ffmpeg_factory_get_dev_count,
120
&ffmpeg_factory_get_dev_info,
121
&ffmpeg_factory_default_param,
122
&ffmpeg_factory_create_stream,
123
&ffmpeg_factory_refresh
126
static pjmedia_vid_dev_stream_op stream_op =
128
&ffmpeg_stream_get_param,
129
&ffmpeg_stream_get_cap,
130
&ffmpeg_stream_set_cap,
131
&ffmpeg_stream_start,
132
&ffmpeg_stream_get_frame,
135
&ffmpeg_stream_destroy
139
static void print_ffmpeg_err(int err)
142
if (av_strerror(err, errbuf, sizeof(errbuf)) >= 0)
143
PJ_LOG(1, (THIS_FILE, "ffmpeg err %d: %s", err, errbuf));
147
static void print_ffmpeg_log(void* ptr, int level, const char* fmt, va_list vl)
150
PJ_UNUSED_ARG(level);
151
vfprintf(stdout, fmt, vl);
155
static pj_status_t ffmpeg_capture_open(AVFormatContext **ctx,
157
const char *dev_name,
158
const pjmedia_vid_dev_param *param)
160
AVFormatParameters fp;
161
pjmedia_video_format_detail *vfd;
164
PJ_ASSERT_RETURN(ctx && ifmt && dev_name && param, PJ_EINVAL);
165
PJ_ASSERT_RETURN(param->fmt.detail_type == PJMEDIA_FORMAT_DETAIL_VIDEO,
168
vfd = pjmedia_format_get_video_format_detail(¶m->fmt, PJ_TRUE);
170
/* Init ffmpeg format context */
171
*ctx = avformat_alloc_context();
173
/* Init ffmpeg format param */
174
pj_bzero(&fp, sizeof(fp));
175
fp.prealloced_context = 1;
176
fp.width = vfd->size.w;
177
fp.height = vfd->size.h;
178
fp.pix_fmt = PIX_FMT_BGR24;
179
fp.time_base.num = vfd->fps.denum;
180
fp.time_base.den = vfd->fps.num;
182
/* Open capture stream */
183
err = av_open_input_stream(ctx, NULL, dev_name, ifmt, &fp);
185
*ctx = NULL; /* ffmpeg freed its states on failure, do we must too */
186
print_ffmpeg_err(err);
193
static void ffmpeg_capture_close(AVFormatContext *ctx)
196
av_close_input_stream(ctx);
200
/****************************************************************************
204
* Init ffmpeg_ video driver.
206
pjmedia_vid_dev_factory* pjmedia_ffmpeg_factory(pj_pool_factory *pf)
211
pool = pj_pool_create(pf, "ffmpeg_cap_dev", 1000, 1000, NULL);
212
f = PJ_POOL_ZALLOC_T(pool, ffmpeg_factory);
216
f->base.op = &factory_op;
218
avdevice_register_all();
224
/* API: init factory */
225
static pj_status_t ffmpeg_factory_init(pjmedia_vid_dev_factory *f)
227
return ffmpeg_factory_refresh(f);
230
/* API: destroy factory */
231
static pj_status_t ffmpeg_factory_destroy(pjmedia_vid_dev_factory *f)
233
ffmpeg_factory *ff = (ffmpeg_factory*)f;
234
pj_pool_t *pool = ff->pool;
239
pj_pool_release(ff->dev_pool);
241
pj_pool_release(pool);
246
/* API: refresh the list of devices */
247
static pj_status_t ffmpeg_factory_refresh(pjmedia_vid_dev_factory *f)
249
ffmpeg_factory *ff = (ffmpeg_factory*)f;
251
ffmpeg_dev_info *info;
253
av_log_set_callback(&print_ffmpeg_log);
254
av_log_set_level(AV_LOG_DEBUG);
257
pj_pool_release(ff->dev_pool);
261
/* TODO: this should enumerate devices, now it enumerates host APIs */
263
ff->dev_pool = pj_pool_create(ff->pf, "ffmpeg_cap_dev", 500, 500, NULL);
265
p = av_iformat_next(NULL);
267
if (p->flags & AVFMT_NOFILE) {
270
info = &ff->dev_info[ff->dev_count++];
271
pj_bzero(info, sizeof(*info));
272
pj_ansi_strncpy(info->base.name, "default",
273
sizeof(info->base.name));
274
pj_ansi_snprintf(info->base.driver, sizeof(info->base.driver),
275
"%s (ffmpeg)", p->name);
276
info->base.dir = PJMEDIA_DIR_CAPTURE;
277
info->base.has_callback = PJ_FALSE;
281
#if defined(PJ_WIN32) && PJ_WIN32!=0
282
info->def_devname = "0";
283
#elif defined(PJ_LINUX) && PJ_LINUX!=0
284
info->def_devname = "/dev/video0";
287
/* Set supported formats, currently hardcoded to RGB24 only */
288
info->base.caps = PJMEDIA_VID_DEV_CAP_FORMAT;
289
info->base.fmt_cnt = 1;
290
for (i = 0; i < info->base.fmt_cnt; ++i) {
291
pjmedia_format *fmt = &info->base.fmt[i];
293
fmt->id = PJMEDIA_FORMAT_RGB24;
294
fmt->type = PJMEDIA_TYPE_VIDEO;
295
fmt->detail_type = PJMEDIA_FORMAT_DETAIL_NONE;
298
p = av_iformat_next(p);
304
/* API: get number of devices */
305
static unsigned ffmpeg_factory_get_dev_count(pjmedia_vid_dev_factory *f)
307
ffmpeg_factory *ff = (ffmpeg_factory*)f;
308
return ff->dev_count;
311
/* API: get device info */
312
static pj_status_t ffmpeg_factory_get_dev_info(pjmedia_vid_dev_factory *f,
314
pjmedia_vid_dev_info *info)
316
ffmpeg_factory *ff = (ffmpeg_factory*)f;
318
PJ_ASSERT_RETURN(index < ff->dev_count, PJMEDIA_EVID_INVDEV);
320
pj_memcpy(info, &ff->dev_info[index].base, sizeof(*info));
325
/* API: create default device parameter */
326
static pj_status_t ffmpeg_factory_default_param(pj_pool_t *pool,
327
pjmedia_vid_dev_factory *f,
329
pjmedia_vid_dev_param *param)
331
ffmpeg_factory *ff = (ffmpeg_factory*)f;
332
ffmpeg_dev_info *info;
334
PJ_ASSERT_RETURN(index < ff->dev_count, PJMEDIA_EVID_INVDEV);
338
info = &ff->dev_info[index];
340
pj_bzero(param, sizeof(*param));
341
param->dir = PJMEDIA_DIR_CAPTURE;
342
param->cap_id = index;
343
param->rend_id = PJMEDIA_VID_INVALID_DEV;
344
param->clock_rate = 0;
346
/* Set the device capabilities here */
347
param->flags = PJMEDIA_VID_DEV_CAP_FORMAT;
348
param->clock_rate = 90000;
349
pjmedia_format_init_video(¶m->fmt, 0, 320, 240, 25, 1);
350
param->fmt.id = info->base.fmt[0].id;
357
/* API: create stream */
358
static pj_status_t ffmpeg_factory_create_stream(
359
pjmedia_vid_dev_factory *f,
360
pjmedia_vid_dev_param *param,
361
const pjmedia_vid_dev_cb *cb,
363
pjmedia_vid_dev_stream **p_vid_strm)
365
ffmpeg_factory *ff = (ffmpeg_factory*)f;
369
PJ_ASSERT_RETURN(f && param && p_vid_strm, PJ_EINVAL);
370
PJ_ASSERT_RETURN(param->dir == PJMEDIA_DIR_CAPTURE, PJ_EINVAL);
371
PJ_ASSERT_RETURN((unsigned)param->cap_id < ff->dev_count, PJ_EINVAL);
372
PJ_ASSERT_RETURN(param->fmt.detail_type == PJMEDIA_FORMAT_DETAIL_VIDEO,
376
PJ_UNUSED_ARG(user_data);
378
/* Create and Initialize stream descriptor */
379
pool = pj_pool_create(ff->pf, "ffmpeg-dev", 1000, 1000, NULL);
380
PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
382
strm = PJ_POOL_ZALLOC_T(pool, struct ffmpeg_stream);
383
strm->factory = (ffmpeg_factory*)f;
385
pj_memcpy(&strm->param, param, sizeof(*param));
388
strm->base.op = &stream_op;
389
*p_vid_strm = &strm->base;
394
/* API: Get stream info. */
395
static pj_status_t ffmpeg_stream_get_param(pjmedia_vid_dev_stream *s,
396
pjmedia_vid_dev_param *pi)
398
ffmpeg_stream *strm = (ffmpeg_stream*)s;
400
PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);
402
pj_memcpy(pi, &strm->param, sizeof(*pi));
407
/* API: get capability */
408
static pj_status_t ffmpeg_stream_get_cap(pjmedia_vid_dev_stream *s,
409
pjmedia_vid_dev_cap cap,
412
ffmpeg_stream *strm = (ffmpeg_stream*)s;
418
return PJMEDIA_EVID_INVCAP;
421
/* API: set capability */
422
static pj_status_t ffmpeg_stream_set_cap(pjmedia_vid_dev_stream *s,
423
pjmedia_vid_dev_cap cap,
426
ffmpeg_stream *strm = (ffmpeg_stream*)s;
432
return PJMEDIA_EVID_INVCAP;
436
/* API: Start stream. */
437
static pj_status_t ffmpeg_stream_start(pjmedia_vid_dev_stream *s)
439
ffmpeg_stream *strm = (ffmpeg_stream*)s;
440
ffmpeg_dev_info *info;
443
info = &strm->factory->dev_info[strm->param.cap_id];
445
PJ_LOG(4, (THIS_FILE, "Starting ffmpeg capture stream"));
447
status = ffmpeg_capture_open(&strm->ff_fmt_ctx, info->host_api,
448
info->def_devname, &strm->param);
449
if (status != PJ_SUCCESS) {
450
/* must set ffmpeg states to NULL on any failure */
451
strm->ff_fmt_ctx = NULL;
458
/* API: Get frame from stream */
459
static pj_status_t ffmpeg_stream_get_frame(pjmedia_vid_dev_stream *s,
460
pjmedia_frame *frame)
462
ffmpeg_stream *strm = (ffmpeg_stream*)s;
466
err = av_read_frame(strm->ff_fmt_ctx, &p);
468
print_ffmpeg_err(err);
472
pj_bzero(frame, sizeof(*frame));
473
frame->type = PJMEDIA_FRAME_TYPE_VIDEO;
475
frame->size = p.size;
481
/* API: Stop stream. */
482
static pj_status_t ffmpeg_stream_stop(pjmedia_vid_dev_stream *s)
484
ffmpeg_stream *strm = (ffmpeg_stream*)s;
486
PJ_LOG(4, (THIS_FILE, "Stopping ffmpeg capture stream"));
488
ffmpeg_capture_close(strm->ff_fmt_ctx);
489
strm->ff_fmt_ctx = NULL;
495
/* API: Destroy stream. */
496
static pj_status_t ffmpeg_stream_destroy(pjmedia_vid_dev_stream *s)
498
ffmpeg_stream *strm = (ffmpeg_stream*)s;
500
PJ_ASSERT_RETURN(strm != NULL, PJ_EINVAL);
502
ffmpeg_stream_stop(s);
504
pj_pool_release(strm->pool);
510
# pragma comment( lib, "avdevice.lib")
511
# pragma comment( lib, "avformat.lib")
512
# pragma comment( lib, "avutil.lib")
516
#endif /* PJMEDIA_VIDEO_DEV_HAS_FFMPEG */