Browse Source

lavd/dshow: support video codec and pixel format selection

Signed-off-by: Stefano Sabatini <stefasab@gmail.com>
tags/n1.0
Ramiro Polla Stefano Sabatini 13 years ago
parent
commit
37a0db50db
2 changed files with 41 additions and 1 deletions
  1. +4
    -0
      doc/indevs.texi
  2. +37
    -1
      libavdevice/dshow.c

+ 4
- 0
doc/indevs.texi View File

@@ -112,6 +112,10 @@ defaults to 0).
Set audio device number for devices with same name (starts at 0, Set audio device number for devices with same name (starts at 0,
defaults to 0). defaults to 0).


@item pixel_format
Select pixel format to be used by DirectShow. This may only be set when
the video codec is not set or set to rawvideo.

@item audio_buffer_size @item audio_buffer_size
Set audio device buffer size in milliseconds (which can directly Set audio device buffer size in milliseconds (which can directly
impact latency, depending on the device). impact latency, depending on the device).


+ 37
- 1
libavdevice/dshow.c View File

@@ -20,6 +20,7 @@
*/ */


#include "libavutil/parseutils.h" #include "libavutil/parseutils.h"
#include "libavutil/pixdesc.h"
#include "libavutil/opt.h" #include "libavutil/opt.h"
#include "libavformat/internal.h" #include "libavformat/internal.h"
#include "avdevice.h" #include "avdevice.h"
@@ -52,6 +53,8 @@ struct dshow_ctx {


IMediaControl *control; IMediaControl *control;


enum PixelFormat pixel_format;
enum AVCodecID video_codec_id;
char *video_size; char *video_size;
char *framerate; char *framerate;


@@ -371,6 +374,18 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
goto next; goto next;
} }
if (!pformat_set) { if (!pformat_set) {
enum PixelFormat pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount);
if (pix_fmt == PIX_FMT_NONE) {
enum AVCodecID codec_id = dshow_codecid(bih->biCompression);
AVCodec *codec = avcodec_find_decoder(codec_id);
if (codec_id == AV_CODEC_ID_NONE || !codec) {
av_log(avctx, AV_LOG_INFO, " unknown compression type");
} else {
av_log(avctx, AV_LOG_INFO, " vcodec=%s", codec->name);
}
} else {
av_log(avctx, AV_LOG_INFO, " pixel_format=%s", av_get_pix_fmt_name(pix_fmt));
}
av_log(avctx, AV_LOG_INFO, " min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n", av_log(avctx, AV_LOG_INFO, " min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n",
vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy, vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy,
1e7 / vcaps->MaxFrameInterval, 1e7 / vcaps->MaxFrameInterval,
@@ -378,6 +393,14 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
1e7 / vcaps->MinFrameInterval); 1e7 / vcaps->MinFrameInterval);
continue; continue;
} }
if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {
if (ctx->video_codec_id != dshow_codecid(bih->biCompression))
goto next;
}
if (ctx->pixel_format != PIX_FMT_NONE &&
ctx->pixel_format != dshow_pixfmt(bih->biCompression, bih->biBitCount)) {
goto next;
}
if (ctx->framerate) { if (ctx->framerate) {
int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000) int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000)
/ ctx->requested_framerate.num; / ctx->requested_framerate.num;
@@ -511,7 +534,9 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio }; const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
const char *devtypename = (devtype == VideoDevice) ? "video" : "audio"; const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";


int set_format = (devtype == VideoDevice && (ctx->video_size || ctx->framerate))
int set_format = (devtype == VideoDevice && (ctx->video_size || ctx->framerate ||
ctx->pixel_format != PIX_FMT_NONE ||
ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO))
|| (devtype == AudioDevice && (ctx->channels || ctx->sample_rate)); || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate));
int format_set = 0; int format_set = 0;


@@ -851,6 +876,16 @@ static int dshow_read_header(AVFormatContext *avctx)
goto error; goto error;
} }


ctx->video_codec_id = avctx->video_codec_id ? avctx->video_codec_id
: AV_CODEC_ID_RAWVIDEO;
if (ctx->pixel_format != PIX_FMT_NONE) {
if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {
av_log(avctx, AV_LOG_ERROR, "Pixel format may only be set when "
"video codec is not set or set to rawvideo\n");
ret = AVERROR(EINVAL);
goto error;
}
}
if (ctx->video_size) { if (ctx->video_size) {
r = av_parse_video_size(&ctx->requested_width, &ctx->requested_height, ctx->video_size); r = av_parse_video_size(&ctx->requested_width, &ctx->requested_height, ctx->video_size);
if (r < 0) { if (r < 0) {
@@ -990,6 +1025,7 @@ static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt)
#define DEC AV_OPT_FLAG_DECODING_PARAM #define DEC AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = { static const AVOption options[] = {
{ "video_size", "set video size given a string such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { "video_size", "set video size given a string such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
{ "pixel_format", "set video pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT, {.str = NULL}, 0, 0, DEC },
{ "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
{ "sample_rate", "set audio sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC }, { "sample_rate", "set audio sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
{ "sample_size", "set audio sample size", OFFSET(sample_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 16, DEC }, { "sample_size", "set audio sample size", OFFSET(sample_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 16, DEC },


Loading…
Cancel
Save