Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
ffmpeg
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
ffmpeg
Commits
d2e6dd32
Commit
d2e6dd32
authored
Mar 04, 2017
by
Mark Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avconv: Generic device setup
Not yet enabled for any hwaccels.
parent
b7487f4f
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
452 additions
and
6 deletions
+452
-6
Makefile
avtools/Makefile
+2
-1
avconv.c
avtools/avconv.c
+22
-0
avconv.h
avtools/avconv.h
+17
-0
avconv_hw.c
avtools/avconv_hw.c
+383
-0
avconv_opt.c
avtools/avconv_opt.c
+28
-5
No files found.
avtools/Makefile
View file @
d2e6dd32
...
...
@@ -8,7 +8,8 @@ PROGS += $(AVPROGS)
AVBASENAMES
=
avconv avplay avprobe
ALLAVPROGS
=
$
(
AVBASENAMES:%
=
%
$(EXESUF)
)
OBJS-avconv
+=
avtools/avconv_opt.o avtools/avconv_filter.o
OBJS-avconv
+=
avtools/avconv_opt.o avtools/avconv_filter.o
\
avtools/avconv_hw.o
OBJS-avconv-$(CONFIG_LIBMFX)
+=
avtools/avconv_qsv.o
OBJS-avconv-$(CONFIG_VAAPI)
+=
avtools/avconv_vaapi.o
OBJS-avconv-$(CONFIG_VDA)
+=
avtools/avconv_vda.o
...
...
avtools/avconv.c
View file @
d2e6dd32
...
...
@@ -1704,6 +1704,17 @@ static int init_input_stream(int ist_index, char *error, int error_len)
if
(
!
av_dict_get
(
ist
->
decoder_opts
,
"threads"
,
NULL
,
0
))
av_dict_set
(
&
ist
->
decoder_opts
,
"threads"
,
"auto"
,
0
);
ret
=
hw_device_setup_for_decode
(
ist
);
if
(
ret
<
0
)
{
char
errbuf
[
128
];
av_strerror
(
ret
,
errbuf
,
sizeof
(
errbuf
));
snprintf
(
error
,
error_len
,
"Device setup failed for "
"decoder on input stream #%d:%d : %s"
,
ist
->
file_index
,
ist
->
st
->
index
,
errbuf
);
return
ret
;
}
if
((
ret
=
avcodec_open2
(
ist
->
dec_ctx
,
codec
,
&
ist
->
decoder_opts
))
<
0
)
{
char
errbuf
[
128
];
if
(
ret
==
AVERROR_EXPERIMENTAL
)
...
...
@@ -2046,6 +2057,16 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len)
ost
->
enc_ctx
->
hw_frames_ctx
=
av_buffer_ref
(
ost
->
filter
->
filter
->
inputs
[
0
]
->
hw_frames_ctx
);
if
(
!
ost
->
enc_ctx
->
hw_frames_ctx
)
return
AVERROR
(
ENOMEM
);
}
else
{
ret
=
hw_device_setup_for_encode
(
ost
);
if
(
ret
<
0
)
{
char
errbuf
[
128
];
av_strerror
(
ret
,
errbuf
,
sizeof
(
errbuf
));
snprintf
(
error
,
error_len
,
"Device setup failed for "
"encoder on output stream #%d:%d : %s"
,
ost
->
file_index
,
ost
->
index
,
errbuf
);
return
ret
;
}
}
if
((
ret
=
avcodec_open2
(
ost
->
enc_ctx
,
codec
,
&
ost
->
encoder_opts
))
<
0
)
{
...
...
@@ -2795,6 +2816,7 @@ static int transcode(void)
}
av_buffer_unref
(
&
hw_device_ctx
);
hw_device_free_all
();
/* finished ! */
ret
=
0
;
...
...
avtools/avconv.h
View file @
d2e6dd32
...
...
@@ -40,6 +40,7 @@
#include "libavutil/avutil.h"
#include "libavutil/dict.h"
#include "libavutil/fifo.h"
#include "libavutil/hwcontext.h"
#include "libavutil/pixfmt.h"
#include "libavutil/rational.h"
...
...
@@ -63,8 +64,15 @@ typedef struct HWAccel {
int
(
*
init
)(
AVCodecContext
*
s
);
enum
HWAccelID
id
;
enum
AVPixelFormat
pix_fmt
;
enum
AVHWDeviceType
device_type
;
}
HWAccel
;
typedef
struct
HWDevice
{
char
*
name
;
enum
AVHWDeviceType
type
;
AVBufferRef
*
device_ref
;
}
HWDevice
;
/* select an input stream for an output stream */
typedef
struct
StreamMap
{
int
disabled
;
/* 1 is this mapping is disabled by a negative map */
...
...
@@ -510,4 +518,13 @@ int qsv_transcode_init(OutputStream *ost);
int
vaapi_decode_init
(
AVCodecContext
*
avctx
);
int
vaapi_device_init
(
const
char
*
device
);
HWDevice
*
hw_device_get_by_name
(
const
char
*
name
);
int
hw_device_init_from_string
(
const
char
*
arg
,
HWDevice
**
dev
);
void
hw_device_free_all
(
void
);
int
hw_device_setup_for_decode
(
InputStream
*
ist
);
int
hw_device_setup_for_encode
(
OutputStream
*
ost
);
int
hwaccel_decode_init
(
AVCodecContext
*
avctx
);
#endif
/* AVCONV_H */
avtools/avconv_hw.c
0 → 100644
View file @
d2e6dd32
/*
* This file is part of Libav.
*
* Libav 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.
*
* Libav 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 Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <string.h>
#include "avconv.h"
static
int
nb_hw_devices
;
static
HWDevice
**
hw_devices
;
static
HWDevice
*
hw_device_get_by_type
(
enum
AVHWDeviceType
type
)
{
HWDevice
*
found
=
NULL
;
int
i
;
for
(
i
=
0
;
i
<
nb_hw_devices
;
i
++
)
{
if
(
hw_devices
[
i
]
->
type
==
type
)
{
if
(
found
)
return
NULL
;
found
=
hw_devices
[
i
];
}
}
return
found
;
}
HWDevice
*
hw_device_get_by_name
(
const
char
*
name
)
{
int
i
;
for
(
i
=
0
;
i
<
nb_hw_devices
;
i
++
)
{
if
(
!
strcmp
(
hw_devices
[
i
]
->
name
,
name
))
return
hw_devices
[
i
];
}
return
NULL
;
}
static
HWDevice
*
hw_device_add
(
void
)
{
int
err
;
err
=
av_reallocp_array
(
&
hw_devices
,
nb_hw_devices
+
1
,
sizeof
(
*
hw_devices
));
if
(
err
)
{
nb_hw_devices
=
0
;
return
NULL
;
}
hw_devices
[
nb_hw_devices
]
=
av_mallocz
(
sizeof
(
HWDevice
));
if
(
!
hw_devices
[
nb_hw_devices
])
return
NULL
;
return
hw_devices
[
nb_hw_devices
++
];
}
int
hw_device_init_from_string
(
const
char
*
arg
,
HWDevice
**
dev_out
)
{
// "type=name:device,key=value,key2=value2"
// "type:device,key=value,key2=value2"
// -> av_hwdevice_ctx_create()
// "type=name@name"
// "type@name"
// -> av_hwdevice_ctx_create_derived()
AVDictionary
*
options
=
NULL
;
char
*
type_name
=
NULL
,
*
name
=
NULL
,
*
device
=
NULL
;
enum
AVHWDeviceType
type
;
HWDevice
*
dev
,
*
src
;
AVBufferRef
*
device_ref
;
int
err
;
const
char
*
errmsg
,
*
p
,
*
q
;
size_t
k
;
k
=
strcspn
(
arg
,
":=@"
);
p
=
arg
+
k
;
type_name
=
av_strndup
(
arg
,
k
);
if
(
!
type_name
)
{
err
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
type
=
av_hwdevice_find_type_by_name
(
type_name
);
if
(
type
==
AV_HWDEVICE_TYPE_NONE
)
{
errmsg
=
"unknown device type"
;
goto
invalid
;
}
if
(
*
p
==
'='
)
{
k
=
strcspn
(
p
+
1
,
":@"
);
name
=
av_strndup
(
p
+
1
,
k
);
if
(
!
name
)
{
err
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
if
(
hw_device_get_by_name
(
name
))
{
errmsg
=
"named device already exists"
;
goto
invalid
;
}
p
+=
1
+
k
;
}
else
{
// Give the device an automatic name of the form "type%d".
// We arbitrarily limit at 1000 anonymous devices of the same
// type - there is probably something else very wrong if you
// get to this limit.
size_t
index_pos
;
int
index
,
index_limit
=
1000
;
index_pos
=
strlen
(
type_name
);
name
=
av_malloc
(
index_pos
+
4
);
if
(
!
name
)
{
err
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
for
(
index
=
0
;
index
<
index_limit
;
index
++
)
{
snprintf
(
name
,
index_pos
+
4
,
"%s%d"
,
type_name
,
index
);
if
(
!
hw_device_get_by_name
(
name
))
break
;
}
if
(
index
>=
index_limit
)
{
errmsg
=
"too many devices"
;
goto
invalid
;
}
}
if
(
!*
p
)
{
// New device with no parameters.
err
=
av_hwdevice_ctx_create
(
&
device_ref
,
type
,
NULL
,
NULL
,
0
);
if
(
err
<
0
)
goto
fail
;
}
else
if
(
*
p
==
':'
)
{
// New device with some parameters.
++
p
;
q
=
strchr
(
p
,
','
);
if
(
q
)
{
device
=
av_strndup
(
p
,
q
-
p
);
if
(
!
device
)
{
err
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
err
=
av_dict_parse_string
(
&
options
,
q
+
1
,
"="
,
","
,
0
);
if
(
err
<
0
)
{
errmsg
=
"failed to parse options"
;
goto
invalid
;
}
}
err
=
av_hwdevice_ctx_create
(
&
device_ref
,
type
,
device
?
device
:
p
,
options
,
0
);
if
(
err
<
0
)
goto
fail
;
}
else
if
(
*
p
==
'@'
)
{
// Derive from existing device.
src
=
hw_device_get_by_name
(
p
+
1
);
if
(
!
src
)
{
errmsg
=
"invalid source device name"
;
goto
invalid
;
}
err
=
av_hwdevice_ctx_create_derived
(
&
device_ref
,
type
,
src
->
device_ref
,
0
);
if
(
err
<
0
)
goto
fail
;
}
else
{
errmsg
=
"parse error"
;
goto
invalid
;
}
dev
=
hw_device_add
();
if
(
!
dev
)
{
err
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
dev
->
name
=
name
;
dev
->
type
=
type
;
dev
->
device_ref
=
device_ref
;
if
(
dev_out
)
*
dev_out
=
dev
;
name
=
NULL
;
err
=
0
;
done:
av_freep
(
&
type_name
);
av_freep
(
&
name
);
av_freep
(
&
device
);
av_dict_free
(
&
options
);
return
err
;
invalid:
av_log
(
NULL
,
AV_LOG_ERROR
,
"Invalid device specification
\"
%s
\"
: %s
\n
"
,
arg
,
errmsg
);
err
=
AVERROR
(
EINVAL
);
goto
done
;
fail:
av_log
(
NULL
,
AV_LOG_ERROR
,
"Device creation failed: %d.
\n
"
,
err
);
goto
done
;
}
void
hw_device_free_all
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
nb_hw_devices
;
i
++
)
{
av_freep
(
&
hw_devices
[
i
]
->
name
);
av_buffer_unref
(
&
hw_devices
[
i
]
->
device_ref
);
av_freep
(
&
hw_devices
[
i
]);
}
av_freep
(
&
hw_devices
);
nb_hw_devices
=
0
;
}
static
enum
AVHWDeviceType
hw_device_match_type_by_hwaccel
(
enum
HWAccelID
hwaccel_id
)
{
int
i
;
if
(
hwaccel_id
==
HWACCEL_NONE
)
return
AV_HWDEVICE_TYPE_NONE
;
for
(
i
=
0
;
hwaccels
[
i
].
name
;
i
++
)
{
if
(
hwaccels
[
i
].
id
==
hwaccel_id
)
return
hwaccels
[
i
].
device_type
;
}
return
AV_HWDEVICE_TYPE_NONE
;
}
static
enum
AVHWDeviceType
hw_device_match_type_in_name
(
const
char
*
codec_name
)
{
const
char
*
type_name
;
enum
AVHWDeviceType
type
;
for
(
type
=
av_hwdevice_iterate_types
(
AV_HWDEVICE_TYPE_NONE
);
type
!=
AV_HWDEVICE_TYPE_NONE
;
type
=
av_hwdevice_iterate_types
(
type
))
{
type_name
=
av_hwdevice_get_type_name
(
type
);
if
(
strstr
(
codec_name
,
type_name
))
return
type
;
}
return
AV_HWDEVICE_TYPE_NONE
;
}
int
hw_device_setup_for_decode
(
InputStream
*
ist
)
{
enum
AVHWDeviceType
type
;
HWDevice
*
dev
;
const
char
*
type_name
;
int
err
;
if
(
ist
->
hwaccel_device
)
{
dev
=
hw_device_get_by_name
(
ist
->
hwaccel_device
);
if
(
!
dev
)
{
char
*
tmp
;
size_t
len
;
type
=
hw_device_match_type_by_hwaccel
(
ist
->
hwaccel_id
);
if
(
type
==
AV_HWDEVICE_TYPE_NONE
)
{
// No match - this isn't necessarily invalid, though,
// because an explicit device might not be needed or
// the hwaccel setup could be handled elsewhere.
return
0
;
}
type_name
=
av_hwdevice_get_type_name
(
type
);
len
=
strlen
(
type_name
)
+
1
+
strlen
(
ist
->
hwaccel_device
)
+
1
;
tmp
=
av_malloc
(
len
);
if
(
!
tmp
)
return
AVERROR
(
ENOMEM
);
snprintf
(
tmp
,
len
,
"%s:%s"
,
type_name
,
ist
->
hwaccel_device
);
err
=
hw_device_init_from_string
(
tmp
,
&
dev
);
av_free
(
tmp
);
if
(
err
<
0
)
return
err
;
}
}
else
{
if
(
ist
->
hwaccel_id
!=
HWACCEL_NONE
)
type
=
hw_device_match_type_by_hwaccel
(
ist
->
hwaccel_id
);
else
type
=
hw_device_match_type_in_name
(
ist
->
dec
->
name
);
if
(
type
!=
AV_HWDEVICE_TYPE_NONE
)
{
dev
=
hw_device_get_by_type
(
type
);
}
else
{
// No device required.
return
0
;
}
}
if
(
!
dev
)
{
av_log
(
ist
->
dec_ctx
,
AV_LOG_WARNING
,
"No device available "
"for decoder (device type %s for codec %s).
\n
"
,
av_hwdevice_get_type_name
(
type
),
ist
->
dec
->
name
);
return
0
;
}
ist
->
dec_ctx
->
hw_device_ctx
=
av_buffer_ref
(
dev
->
device_ref
);
if
(
!
ist
->
dec_ctx
->
hw_device_ctx
)
return
AVERROR
(
ENOMEM
);
return
0
;
}
int
hw_device_setup_for_encode
(
OutputStream
*
ost
)
{
enum
AVHWDeviceType
type
;
HWDevice
*
dev
;
type
=
hw_device_match_type_in_name
(
ost
->
enc
->
name
);
if
(
type
!=
AV_HWDEVICE_TYPE_NONE
)
{
dev
=
hw_device_get_by_type
(
type
);
if
(
!
dev
)
{
av_log
(
ost
->
enc_ctx
,
AV_LOG_WARNING
,
"No device available "
"for encoder (device type %s for codec %s).
\n
"
,
av_hwdevice_get_type_name
(
type
),
ost
->
enc
->
name
);
return
0
;
}
ost
->
enc_ctx
->
hw_device_ctx
=
av_buffer_ref
(
dev
->
device_ref
);
if
(
!
ost
->
enc_ctx
->
hw_device_ctx
)
return
AVERROR
(
ENOMEM
);
return
0
;
}
else
{
// No device required.
return
0
;
}
}
static
int
hwaccel_retrieve_data
(
AVCodecContext
*
avctx
,
AVFrame
*
input
)
{
InputStream
*
ist
=
avctx
->
opaque
;
AVFrame
*
output
=
NULL
;
enum
AVPixelFormat
output_format
=
ist
->
hwaccel_output_format
;
int
err
;
if
(
input
->
format
==
output_format
)
{
// Nothing to do.
return
0
;
}
output
=
av_frame_alloc
();
if
(
!
output
)
return
AVERROR
(
ENOMEM
);
output
->
format
=
output_format
;
err
=
av_hwframe_transfer_data
(
output
,
input
,
0
);
if
(
err
<
0
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Failed to transfer data to "
"output frame: %d.
\n
"
,
err
);
goto
fail
;
}
err
=
av_frame_copy_props
(
output
,
input
);
if
(
err
<
0
)
{
av_frame_unref
(
output
);
goto
fail
;
}
av_frame_unref
(
input
);
av_frame_move_ref
(
input
,
output
);
av_frame_free
(
&
output
);
return
0
;
fail:
av_frame_free
(
&
output
);
return
err
;
}
int
hwaccel_decode_init
(
AVCodecContext
*
avctx
)
{
InputStream
*
ist
=
avctx
->
opaque
;
ist
->
hwaccel_retrieve_data
=
&
hwaccel_retrieve_data
;
return
0
;
}
avtools/avconv_opt.c
View file @
d2e6dd32
...
...
@@ -57,19 +57,24 @@
const
HWAccel
hwaccels
[]
=
{
#if HAVE_VDPAU_X11
{
"vdpau"
,
vdpau_init
,
HWACCEL_VDPAU
,
AV_PIX_FMT_VDPAU
},
{
"vdpau"
,
vdpau_init
,
HWACCEL_VDPAU
,
AV_PIX_FMT_VDPAU
,
AV_HWDEVICE_TYPE_NONE
},
#endif
#if HAVE_DXVA2_LIB
{
"dxva2"
,
dxva2_init
,
HWACCEL_DXVA2
,
AV_PIX_FMT_DXVA2_VLD
},
{
"dxva2"
,
dxva2_init
,
HWACCEL_DXVA2
,
AV_PIX_FMT_DXVA2_VLD
,
AV_HWDEVICE_TYPE_NONE
},
#endif
#if CONFIG_VDA
{
"vda"
,
vda_init
,
HWACCEL_VDA
,
AV_PIX_FMT_VDA
},
{
"vda"
,
vda_init
,
HWACCEL_VDA
,
AV_PIX_FMT_VDA
,
AV_HWDEVICE_TYPE_NONE
},
#endif
#if CONFIG_LIBMFX
{
"qsv"
,
qsv_init
,
HWACCEL_QSV
,
AV_PIX_FMT_QSV
},
{
"qsv"
,
qsv_init
,
HWACCEL_QSV
,
AV_PIX_FMT_QSV
,
AV_HWDEVICE_TYPE_NONE
},
#endif
#if CONFIG_VAAPI
{
"vaapi"
,
vaapi_decode_init
,
HWACCEL_VAAPI
,
AV_PIX_FMT_VAAPI
},
{
"vaapi"
,
vaapi_decode_init
,
HWACCEL_VAAPI
,
AV_PIX_FMT_VAAPI
,
AV_HWDEVICE_TYPE_NONE
},
#endif
{
0
},
};
...
...
@@ -337,6 +342,21 @@ static int opt_vaapi_device(void *optctx, const char *opt, const char *arg)
}
#endif
static
int
opt_init_hw_device
(
void
*
optctx
,
const
char
*
opt
,
const
char
*
arg
)
{
if
(
!
strcmp
(
arg
,
"list"
))
{
enum
AVHWDeviceType
type
=
AV_HWDEVICE_TYPE_NONE
;
printf
(
"Supported hardware device types:
\n
"
);
while
((
type
=
av_hwdevice_iterate_types
(
type
))
!=
AV_HWDEVICE_TYPE_NONE
)
printf
(
"%s
\n
"
,
av_hwdevice_get_type_name
(
type
));
printf
(
"
\n
"
);
exit_program
(
0
);
}
else
{
return
hw_device_init_from_string
(
arg
,
NULL
);
}
}
/**
* Parse a metadata specifier passed as 'arg' parameter.
* @param arg metadata string to parse
...
...
@@ -2741,5 +2761,8 @@ const OptionDef options[] = {
"set VAAPI hardware device (DRM path or X11 display name)"
,
"device"
},
#endif
{
"init_hw_device"
,
HAS_ARG
|
OPT_EXPERT
,
{
.
func_arg
=
opt_init_hw_device
},
"initialise hardware device"
,
"args"
},
{
NULL
,
},
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment