mirror of
https://gitee.com/openharmony/third_party_ffmpeg
synced 2025-02-25 15:33:49 +00:00
Merge remote-tracking branch 'cigaes/master'
* cigaes/master: lavfi/drawtext: allow to format pts as HH:MM:SS.mmm. lavf/concatdec: implement automatic conversions. lavf/concatdec: reindent after last commit. lavf/concatdec: always do stream matching. lavf/concatdec: check match_streams() return value. lavf/concatdec: use a structure for each stream. ffprobe: use the codec descriptor if no decoder was found. lavf/matroska: add "binary" pseudo-MIME type. lavc: minor bump and APIchanges for AVCodecDescriptor.mime_types. lavc: add a mime_types field to codec descriptors. lavc: add AV_CODEC_ID_BIN_DATA. lavc: add codec descriptors for TTF and OTF. lavc: add codec descriptors for deprecated ids. lavc/codec_desc: add separation comment. tools/ffhash: implement base64 output. tools/ffhash: use av_hash_final_hex(). lavu/hash: add hash_final helpers. Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
commit
03b88f6b39
@ -15,6 +15,12 @@ libavutil: 2012-10-22
|
||||
|
||||
API changes, most recent first:
|
||||
|
||||
2014-04-29 - 1bf6396 - lavc 55.60.100 - avcodec.h
|
||||
Add AVCodecDescriptor.mime_types field.
|
||||
|
||||
2014-04-29 - xxxxxxx - lavu 52.80.0 - hash.h
|
||||
Add av_hash_final_bin(), av_hash_final_hex() and av_hash_final_b64().
|
||||
|
||||
2014-03-07 - 8b2a130 - lavc 55.50.0 / 55.53.100 - dxva2.h
|
||||
Add FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO for old Intel GPUs.
|
||||
|
||||
|
@ -128,6 +128,14 @@ If set to 0, any file name is accepted.
|
||||
The default is -1, it is equivalent to 1 if the format was automatically
|
||||
probed and 0 otherwise.
|
||||
|
||||
@item auto_convert
|
||||
If set to 1, try to perform automatic conversions on packet data to make the
|
||||
streams concatenable.
|
||||
|
||||
Currently, the only conversion is adding the h264_mp4toannexb bitstream
|
||||
filter to H.264 streams in MP4 format. This is necessary in particular if
|
||||
there are resolution changes.
|
||||
|
||||
@end table
|
||||
|
||||
@section flv
|
||||
|
@ -3850,7 +3850,14 @@ The frame number, starting from 0.
|
||||
A 1 character description of the current picture type.
|
||||
|
||||
@item pts
|
||||
The timestamp of the current frame, in seconds, with microsecond accuracy.
|
||||
The timestamp of the current frame.
|
||||
It can take up to two arguments.
|
||||
|
||||
The first argument is the format of the timestamp; it defaults to @code{flt}
|
||||
for seconds as a decimal number with microsecond accuracy; @code{hms} stands
|
||||
for a formatted @var{[-]HH:MM:SS.mmm} timestamp with millisecond accuracy.
|
||||
|
||||
The second argument is an offset added to the timestamp.
|
||||
|
||||
@end table
|
||||
|
||||
|
@ -1976,6 +1976,7 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
|
||||
const char *s;
|
||||
AVRational sar, dar;
|
||||
AVBPrint pbuf;
|
||||
const AVCodecDescriptor *cd;
|
||||
int ret = 0;
|
||||
|
||||
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
|
||||
@ -1993,6 +1994,12 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
|
||||
if (dec->long_name) print_str ("codec_long_name", dec->long_name);
|
||||
else print_str_opt("codec_long_name", "unknown");
|
||||
}
|
||||
} else if ((cd = avcodec_descriptor_get(stream->codec->codec_id))) {
|
||||
print_str_opt("codec_name", cd->name);
|
||||
if (!do_bitexact) {
|
||||
print_str_opt("codec_long_name",
|
||||
cd->long_name ? cd->long_name : "unknown");
|
||||
}
|
||||
} else {
|
||||
print_str_opt("codec_name", "unknown");
|
||||
if (!do_bitexact) {
|
||||
|
@ -533,6 +533,7 @@ enum AVCodecID {
|
||||
AV_CODEC_ID_SMPTE_KLV = MKBETAG('K','L','V','A'),
|
||||
AV_CODEC_ID_DVD_NAV = MKBETAG('D','N','A','V'),
|
||||
AV_CODEC_ID_TIMED_ID3 = MKBETAG('T','I','D','3'),
|
||||
AV_CODEC_ID_BIN_DATA = MKBETAG('D','A','T','A'),
|
||||
|
||||
|
||||
AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it
|
||||
@ -570,6 +571,13 @@ typedef struct AVCodecDescriptor {
|
||||
* Codec properties, a combination of AV_CODEC_PROP_* flags.
|
||||
*/
|
||||
int props;
|
||||
|
||||
/**
|
||||
* MIME type(s) associated with the codec.
|
||||
* May be NULL; if not, a NULL-terminated array of MIME types.
|
||||
* The first item is always non-NULL and is the prefered MIME type.
|
||||
*/
|
||||
const char *const *mime_types;
|
||||
} AVCodecDescriptor;
|
||||
|
||||
/**
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "avcodec.h"
|
||||
#include "version.h"
|
||||
|
||||
#define MT(...) (const char *const[]){ __VA_ARGS__, NULL }
|
||||
|
||||
static const AVCodecDescriptor codec_descriptors[] = {
|
||||
/* video codecs */
|
||||
{
|
||||
@ -85,6 +87,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.name = "mjpeg",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Motion JPEG"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
|
||||
.mime_types= MT("image/jpeg"),
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_MJPEGB,
|
||||
@ -526,6 +529,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.name = "bmp",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("BMP (Windows and OS/2 bitmap)"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
|
||||
.mime_types= MT("image/x-ms-bmp"),
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_CSCD,
|
||||
@ -597,6 +601,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY |
|
||||
AV_CODEC_PROP_LOSSLESS,
|
||||
.mime_types= MT("image/jp2"),
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_VMNC,
|
||||
@ -1277,6 +1282,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.name = "gif",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"),
|
||||
.props = AV_CODEC_PROP_LOSSLESS,
|
||||
.mime_types= MT("image/gif"),
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_JPEGLS,
|
||||
@ -1299,6 +1305,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.name = "pam",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
|
||||
.mime_types= MT("image/x-portable-pixmap"),
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_PBM,
|
||||
@ -1313,6 +1320,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.name = "pcx",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
|
||||
.mime_types= MT("image/x-pcx"),
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_PGM,
|
||||
@ -1334,6 +1342,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.name = "png",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"),
|
||||
.props = AV_CODEC_PROP_LOSSLESS,
|
||||
.mime_types= MT("image/png"),
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_PPM,
|
||||
@ -1376,6 +1385,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.name = "targa",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
|
||||
.mime_types= MT("image/x-targa", "image/x-tga"),
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_TIFF,
|
||||
@ -1383,6 +1393,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.name = "tiff",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("TIFF image"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
|
||||
.mime_types= MT("image/tiff"),
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_TXD,
|
||||
@ -1405,6 +1416,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.long_name = NULL_IF_CONFIG_SMALL("WebP"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY |
|
||||
AV_CODEC_PROP_LOSSLESS,
|
||||
.mime_types= MT("image/webp"),
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_WMV3IMAGE,
|
||||
@ -1426,6 +1438,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.name = "xwd",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
|
||||
.mime_types= MT("image/x-xwindowdump"),
|
||||
},
|
||||
|
||||
/* various PCM "codecs" */
|
||||
@ -2649,6 +2662,15 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"),
|
||||
.props = AV_CODEC_PROP_TEXT_SUB,
|
||||
},
|
||||
|
||||
/* other kind of codecs and pseudo-codecs */
|
||||
{
|
||||
.id = AV_CODEC_ID_TTF,
|
||||
.type = AVMEDIA_TYPE_DATA,
|
||||
.name = "ttf",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("TrueType font"),
|
||||
.mime_types= MT("application/x-truetype-font", "application/x-font"),
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_BINTEXT,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
@ -2670,6 +2692,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.long_name = NULL_IF_CONFIG_SMALL("iCEDraw text"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_OTF,
|
||||
.type = AVMEDIA_TYPE_DATA,
|
||||
.name = "otf",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("OpenType font"),
|
||||
.mime_types= MT("application/vnd.ms-opentype"),
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_SMPTE_KLV,
|
||||
.type = AVMEDIA_TYPE_DATA,
|
||||
@ -2688,7 +2717,130 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.name = "timed_id3",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("timed ID3 metadata"),
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_BIN_DATA,
|
||||
.type = AVMEDIA_TYPE_DATA,
|
||||
.name = "bin_data",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("binary data"),
|
||||
.mime_types= MT("application/octet-stream"),
|
||||
},
|
||||
|
||||
/* deprecated codec ids */
|
||||
{
|
||||
.id = AV_CODEC_ID_BRENDER_PIX_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.name = "brender_pix_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("BRender PIX image (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_ESCAPE130_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.name = "escape130_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Escape 130 (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_EXR_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.name = "exr_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("OpenEXR image (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY |
|
||||
AV_CODEC_PROP_LOSSLESS,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_G2M_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.name = "g2m_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Go2Meeting (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_HEVC_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.name = "hevc_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("H.265 / HEVC (High Efficiency Video Coding) (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_PAF_VIDEO_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.name = "paf_video_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_SANM_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.name = "sanm_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("LucasArts SANM/SMUSH video (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_VP7_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.name = "vp7_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("On2 VP7 (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_WEBP_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.name = "webp_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("WebP (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY |
|
||||
AV_CODEC_PROP_LOSSLESS,
|
||||
},
|
||||
|
||||
{
|
||||
.id = AV_CODEC_ID_VIMA,
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.name = "vima",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_ADPCM_VIMA_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.name = "adpcm_vima_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_OPUS_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.name = "opus_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Opus (Opus Interactive Audio Codec) (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_PAF_AUDIO_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.name = "paf_audio_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Audio (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_PCM_S24LE_PLANAR_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.name = "pcm_s24le_planar_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("PCM signed 24-bit little-endian planar (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_LOSSLESS,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_PCM_S32LE_PLANAR_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.name = "pcm_s32le_planar_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("PCM signed 32-bit little-endian planar (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_LOSSLESS,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_TAK_DEPRECATED,
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.name = "tak_deprecated",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("TAK (Tom's lossless Audio Kompressor) (deprecated id)"),
|
||||
.props = AV_CODEC_PROP_LOSSLESS,
|
||||
},
|
||||
};
|
||||
|
||||
const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id)
|
||||
|
@ -29,8 +29,8 @@
|
||||
#include "libavutil/version.h"
|
||||
|
||||
#define LIBAVCODEC_VERSION_MAJOR 55
|
||||
#define LIBAVCODEC_VERSION_MINOR 59
|
||||
#define LIBAVCODEC_VERSION_MICRO 101
|
||||
#define LIBAVCODEC_VERSION_MINOR 60
|
||||
#define LIBAVCODEC_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||
LIBAVCODEC_VERSION_MINOR, \
|
||||
|
@ -699,8 +699,41 @@ static int func_pts(AVFilterContext *ctx, AVBPrint *bp,
|
||||
char *fct, unsigned argc, char **argv, int tag)
|
||||
{
|
||||
DrawTextContext *s = ctx->priv;
|
||||
const char *fmt;
|
||||
double pts = s->var_values[VAR_T];
|
||||
int ret;
|
||||
|
||||
av_bprintf(bp, "%.6f", s->var_values[VAR_T]);
|
||||
fmt = argc >= 1 ? argv[0] : "flt";
|
||||
if (argc >= 2) {
|
||||
int64_t delta;
|
||||
if ((ret = av_parse_time(&delta, argv[1], 1)) < 0) {
|
||||
av_log(ctx, AV_LOG_ERROR, "Invalid delta '%s'\n", argv[1]);
|
||||
return ret;
|
||||
}
|
||||
pts += (double)delta / AV_TIME_BASE;
|
||||
}
|
||||
if (!strcmp(fmt, "flt")) {
|
||||
av_bprintf(bp, "%.6f", s->var_values[VAR_T]);
|
||||
} else if (!strcmp(fmt, "hms")) {
|
||||
if (isnan(pts)) {
|
||||
av_bprintf(bp, " ??:??:??.???");
|
||||
} else {
|
||||
int64_t ms = round(pts * 1000);
|
||||
char sign = ' ';
|
||||
if (ms < 0) {
|
||||
sign = '-';
|
||||
ms = -ms;
|
||||
}
|
||||
av_bprintf(bp, "%c%02d:%02d:%02d.%03d", sign,
|
||||
(int)(ms / (60 * 60 * 1000)),
|
||||
(int)(ms / (60 * 1000)) % 60,
|
||||
(int)(ms / 1000) % 60,
|
||||
(int)ms % 1000);
|
||||
}
|
||||
} else {
|
||||
av_log(ctx, AV_LOG_ERROR, "Invalid format '%s'\n", fmt);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -776,7 +809,7 @@ static const struct drawtext_function {
|
||||
{ "expr", 1, 1, 0, func_eval_expr },
|
||||
{ "e", 1, 1, 0, func_eval_expr },
|
||||
{ "pict_type", 0, 0, 0, func_pict_type },
|
||||
{ "pts", 0, 0, 0, func_pts },
|
||||
{ "pts", 0, 2, 0, func_pts },
|
||||
{ "gmtime", 0, 1, 'G', func_strftime },
|
||||
{ "localtime", 0, 1, 'L', func_strftime },
|
||||
{ "frame_num", 0, 0, 0, func_frame_num },
|
||||
|
@ -18,19 +18,31 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/avstring.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "libavutil/parseutils.h"
|
||||
#include "avformat.h"
|
||||
#include "internal.h"
|
||||
#include "url.h"
|
||||
|
||||
typedef enum ConcatMatchMode {
|
||||
MATCH_ONE_TO_ONE,
|
||||
MATCH_EXACT_ID,
|
||||
} ConcatMatchMode;
|
||||
|
||||
typedef struct ConcatStream {
|
||||
AVBitStreamFilterContext *bsf;
|
||||
int out_stream_index;
|
||||
} ConcatStream;
|
||||
|
||||
typedef struct {
|
||||
char *url;
|
||||
int64_t start_time;
|
||||
int64_t duration;
|
||||
int *stream_map;
|
||||
int stream_map_size;
|
||||
ConcatStream *streams;
|
||||
int nb_streams;
|
||||
} ConcatFile;
|
||||
|
||||
typedef struct {
|
||||
@ -41,7 +53,8 @@ typedef struct {
|
||||
AVFormatContext *avf;
|
||||
int safe;
|
||||
int seekable;
|
||||
int match_streams;
|
||||
ConcatMatchMode stream_match_mode;
|
||||
unsigned auto_convert;
|
||||
} ConcatContext;
|
||||
|
||||
static int concat_probe(AVProbeData *probe)
|
||||
@ -141,6 +154,17 @@ static int copy_stream_props(AVStream *st, AVStream *source_st)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (st->codec->codec_id || !source_st->codec->codec_id) {
|
||||
if (st->codec->extradata_size < source_st->codec->extradata_size) {
|
||||
ret = ff_alloc_extradata(st->codec,
|
||||
source_st->codec->extradata_size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
memcpy(st->codec->extradata, source_st->codec->extradata,
|
||||
source_st->codec->extradata_size);
|
||||
return 0;
|
||||
}
|
||||
if ((ret = avcodec_copy_context(st->codec, source_st->codec)) < 0)
|
||||
return ret;
|
||||
st->r_frame_rate = source_st->r_frame_rate;
|
||||
@ -150,38 +174,103 @@ static int copy_stream_props(AVStream *st, AVStream *source_st)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int match_streams(AVFormatContext *avf)
|
||||
static int detect_stream_specific(AVFormatContext *avf, int idx)
|
||||
{
|
||||
ConcatContext *cat = avf->priv_data;
|
||||
AVStream *st = cat->avf->streams[idx];
|
||||
ConcatStream *cs = &cat->cur_file->streams[idx];
|
||||
AVBitStreamFilterContext *bsf;
|
||||
|
||||
if (cat->auto_convert && st->codec->codec_id == AV_CODEC_ID_H264 &&
|
||||
(st->codec->extradata_size < 4 || AV_RB32(st->codec->extradata) != 1)) {
|
||||
av_log(cat->avf, AV_LOG_INFO,
|
||||
"Auto-inserting h264_mp4toannexb bitstream filter\n");
|
||||
if (!(bsf = av_bitstream_filter_init("h264_mp4toannexb"))) {
|
||||
av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb bitstream filter "
|
||||
"required for H.264 streams\n");
|
||||
return AVERROR_BSF_NOT_FOUND;
|
||||
}
|
||||
cs->bsf = bsf;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int match_streams_one_to_one(AVFormatContext *avf)
|
||||
{
|
||||
ConcatContext *cat = avf->priv_data;
|
||||
AVStream *st;
|
||||
int *map, i, j, ret;
|
||||
int i, ret;
|
||||
|
||||
if (!cat->match_streams ||
|
||||
cat->cur_file->stream_map_size >= cat->avf->nb_streams)
|
||||
return 0;
|
||||
map = av_realloc(cat->cur_file->stream_map,
|
||||
cat->avf->nb_streams * sizeof(*map));
|
||||
if (!map)
|
||||
return AVERROR(ENOMEM);
|
||||
cat->cur_file->stream_map = map;
|
||||
for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) {
|
||||
if (i < avf->nb_streams) {
|
||||
st = avf->streams[i];
|
||||
} else {
|
||||
if (!(st = avformat_new_stream(avf, NULL)))
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
if ((ret = copy_stream_props(st, cat->avf->streams[i])) < 0)
|
||||
return ret;
|
||||
cat->cur_file->streams[i].out_stream_index = i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = cat->cur_file->stream_map_size; i < cat->avf->nb_streams; i++) {
|
||||
static int match_streams_exact_id(AVFormatContext *avf)
|
||||
{
|
||||
ConcatContext *cat = avf->priv_data;
|
||||
AVStream *st;
|
||||
int i, j, ret;
|
||||
|
||||
for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) {
|
||||
st = cat->avf->streams[i];
|
||||
map[i] = -1;
|
||||
for (j = 0; j < avf->nb_streams; j++) {
|
||||
if (avf->streams[j]->id == st->id) {
|
||||
av_log(avf, AV_LOG_VERBOSE,
|
||||
"Match slave stream #%d with stream #%d id 0x%x\n",
|
||||
i, j, st->id);
|
||||
map[i] = j;
|
||||
if (!avf->streams[j]->codec->codec_id && st->codec->codec_id)
|
||||
if ((ret = copy_stream_props(avf->streams[j], st)) < 0)
|
||||
return ret;
|
||||
if ((ret = copy_stream_props(avf->streams[j], st)) < 0)
|
||||
return ret;
|
||||
cat->cur_file->streams[i].out_stream_index = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
cat->cur_file->stream_map_size = cat->avf->nb_streams;
|
||||
static int match_streams(AVFormatContext *avf)
|
||||
{
|
||||
ConcatContext *cat = avf->priv_data;
|
||||
ConcatStream *map;
|
||||
int i, ret;
|
||||
|
||||
if (cat->cur_file->nb_streams >= cat->avf->nb_streams)
|
||||
return 0;
|
||||
map = av_realloc(cat->cur_file->streams,
|
||||
cat->avf->nb_streams * sizeof(*map));
|
||||
if (!map)
|
||||
return AVERROR(ENOMEM);
|
||||
cat->cur_file->streams = map;
|
||||
memset(map + cat->cur_file->nb_streams, 0,
|
||||
(cat->avf->nb_streams - cat->cur_file->nb_streams) * sizeof(*map));
|
||||
|
||||
for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++)
|
||||
map[i].out_stream_index = -1;
|
||||
switch (cat->stream_match_mode) {
|
||||
case MATCH_ONE_TO_ONE:
|
||||
ret = match_streams_one_to_one(avf);
|
||||
break;
|
||||
case MATCH_EXACT_ID:
|
||||
ret = match_streams_exact_id(avf);
|
||||
break;
|
||||
default:
|
||||
ret = AVERROR_BUG;
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++)
|
||||
if ((ret = detect_stream_specific(avf, i)) < 0)
|
||||
return ret;
|
||||
cat->cur_file->nb_streams = cat->avf->nb_streams;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -222,8 +311,10 @@ static int concat_read_close(AVFormatContext *avf)
|
||||
|
||||
if (cat->avf)
|
||||
avformat_close_input(&cat->avf);
|
||||
for (i = 0; i < cat->nb_files; i++)
|
||||
for (i = 0; i < cat->nb_files; i++) {
|
||||
av_freep(&cat->files[i].url);
|
||||
av_freep(&cat->files[i].streams);
|
||||
}
|
||||
av_freep(&cat->files);
|
||||
return 0;
|
||||
}
|
||||
@ -236,7 +327,6 @@ static int concat_read_header(AVFormatContext *avf)
|
||||
int ret, line = 0, i;
|
||||
unsigned nb_files_alloc = 0;
|
||||
ConcatFile *file = NULL;
|
||||
AVStream *st;
|
||||
int64_t time = 0;
|
||||
|
||||
while (1) {
|
||||
@ -315,18 +405,10 @@ static int concat_read_header(AVFormatContext *avf)
|
||||
cat->seekable = 1;
|
||||
}
|
||||
|
||||
cat->match_streams = !!avf->nb_streams;
|
||||
cat->stream_match_mode = avf->nb_streams ? MATCH_EXACT_ID :
|
||||
MATCH_ONE_TO_ONE;
|
||||
if ((ret = open_file(avf, 0)) < 0)
|
||||
FAIL(ret);
|
||||
if (!cat->match_streams) {
|
||||
for (i = 0; i < cat->avf->nb_streams; i++) {
|
||||
if (!(st = avformat_new_stream(avf, NULL)))
|
||||
FAIL(AVERROR(ENOMEM));
|
||||
if ((ret = copy_stream_props(st, cat->avf->streams[i])) < 0)
|
||||
FAIL(ret);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@ -347,11 +429,52 @@ static int open_next_file(AVFormatContext *avf)
|
||||
return open_file(avf, fileno);
|
||||
}
|
||||
|
||||
static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt)
|
||||
{
|
||||
AVStream *st = avf->streams[cs->out_stream_index];
|
||||
AVBitStreamFilterContext *bsf;
|
||||
AVPacket pkt2;
|
||||
int ret;
|
||||
|
||||
av_assert0(cs->out_stream_index >= 0);
|
||||
for (bsf = cs->bsf; bsf; bsf = bsf->next) {
|
||||
pkt2 = *pkt;
|
||||
ret = av_bitstream_filter_filter(bsf, st->codec, NULL,
|
||||
&pkt2.data, &pkt2.size,
|
||||
pkt->data, pkt->size,
|
||||
!!(pkt->flags & AV_PKT_FLAG_KEY));
|
||||
if (ret < 0) {
|
||||
av_packet_unref(pkt);
|
||||
return ret;
|
||||
}
|
||||
av_assert0(pkt2.buf);
|
||||
if (ret == 0 && pkt2.data != pkt->data) {
|
||||
if ((ret = av_copy_packet(&pkt2, pkt)) < 0) {
|
||||
av_free(pkt2.data);
|
||||
return ret;
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
if (ret > 0) {
|
||||
av_free_packet(pkt);
|
||||
pkt2.buf = av_buffer_create(pkt2.data, pkt2.size,
|
||||
av_buffer_default_free, NULL, 0);
|
||||
if (!pkt2.buf) {
|
||||
av_free(pkt2.data);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
}
|
||||
*pkt = pkt2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
|
||||
{
|
||||
ConcatContext *cat = avf->priv_data;
|
||||
int ret;
|
||||
int64_t delta;
|
||||
ConcatStream *cs;
|
||||
|
||||
while (1) {
|
||||
ret = av_read_frame(cat->avf, pkt);
|
||||
@ -362,16 +485,20 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (cat->match_streams) {
|
||||
match_streams(avf);
|
||||
pkt->stream_index = cat->cur_file->stream_map[pkt->stream_index];
|
||||
if (pkt->stream_index < 0) {
|
||||
av_packet_unref(pkt);
|
||||
continue;
|
||||
}
|
||||
if ((ret = match_streams(avf)) < 0) {
|
||||
av_packet_unref(pkt);
|
||||
return ret;
|
||||
}
|
||||
cs = &cat->cur_file->streams[pkt->stream_index];
|
||||
if (cs->out_stream_index < 0) {
|
||||
av_packet_unref(pkt);
|
||||
continue;
|
||||
}
|
||||
pkt->stream_index = cs->out_stream_index;
|
||||
break;
|
||||
}
|
||||
if ((ret = filter_packet(avf, cs, pkt)))
|
||||
return ret;
|
||||
|
||||
delta = av_rescale_q(cat->cur_file->start_time - cat->avf->start_time,
|
||||
AV_TIME_BASE_Q,
|
||||
@ -478,6 +605,8 @@ static int concat_seek(AVFormatContext *avf, int stream,
|
||||
static const AVOption options[] = {
|
||||
{ "safe", "enable safe mode",
|
||||
OFFSET(safe), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, DEC },
|
||||
{ "auto_convert", "automatically convert bitstream format",
|
||||
OFFSET(auto_convert), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -113,6 +113,7 @@ const CodecMime ff_mkv_mime_tags[] = {
|
||||
{"application/x-truetype-font", AV_CODEC_ID_TTF},
|
||||
{"application/x-font" , AV_CODEC_ID_TTF},
|
||||
{"application/vnd.ms-opentype", AV_CODEC_ID_OTF},
|
||||
{"binary" , AV_CODEC_ID_BIN_DATA},
|
||||
|
||||
{"" , AV_CODEC_ID_NONE}
|
||||
};
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "sha512.h"
|
||||
|
||||
#include "avstring.h"
|
||||
#include "base64.h"
|
||||
#include "error.h"
|
||||
#include "intreadwrite.h"
|
||||
#include "mem.h"
|
||||
@ -196,6 +197,40 @@ void av_hash_final(AVHashContext *ctx, uint8_t *dst)
|
||||
}
|
||||
}
|
||||
|
||||
void av_hash_final_bin(struct AVHashContext *ctx, uint8_t *dst, int size)
|
||||
{
|
||||
uint8_t buf[AV_HASH_MAX_SIZE];
|
||||
unsigned rsize = av_hash_get_size(ctx);
|
||||
|
||||
av_hash_final(ctx, buf);
|
||||
memcpy(dst, buf, FFMIN(size, rsize));
|
||||
if (size > rsize)
|
||||
memset(dst + rsize, 0, size - rsize);
|
||||
}
|
||||
|
||||
void av_hash_final_hex(struct AVHashContext *ctx, uint8_t *dst, int size)
|
||||
{
|
||||
uint8_t buf[AV_HASH_MAX_SIZE];
|
||||
unsigned rsize = av_hash_get_size(ctx), i;
|
||||
|
||||
av_hash_final(ctx, buf);
|
||||
for (i = 0; i < FFMIN(rsize, size / 2); i++)
|
||||
snprintf(dst + i * 2, size - i * 2, "%02x", buf[i]);
|
||||
}
|
||||
|
||||
void av_hash_final_b64(struct AVHashContext *ctx, uint8_t *dst, int size)
|
||||
{
|
||||
uint8_t buf[AV_HASH_MAX_SIZE], b64[AV_BASE64_SIZE(AV_HASH_MAX_SIZE)];
|
||||
unsigned rsize = av_hash_get_size(ctx), osize;
|
||||
|
||||
av_hash_final(ctx, buf);
|
||||
av_base64_encode(b64, sizeof(b64), buf, rsize);
|
||||
osize = AV_BASE64_SIZE(rsize);
|
||||
memcpy(dst, b64, FFMIN(osize, size));
|
||||
if (size < osize)
|
||||
dst[size - 1] = 0;
|
||||
}
|
||||
|
||||
void av_hash_freep(AVHashContext **ctx)
|
||||
{
|
||||
if (*ctx)
|
||||
|
@ -82,6 +82,28 @@ void av_hash_update(struct AVHashContext *ctx, const uint8_t *src, int len);
|
||||
*/
|
||||
void av_hash_final(struct AVHashContext *ctx, uint8_t *dst);
|
||||
|
||||
/**
|
||||
* Finalize a hash context and compute the actual hash value.
|
||||
* If size is smaller than the hash size, the hash is truncated;
|
||||
* if size is larger, the buffer is padded with 0.
|
||||
*/
|
||||
void av_hash_final_bin(struct AVHashContext *ctx, uint8_t *dst, int size);
|
||||
|
||||
/**
|
||||
* Finalize a hash context and compute the actual hash value as a hex string.
|
||||
* The string is always 0-terminated.
|
||||
* If size is smaller than 2 * hash_size + 1, the hex string is truncated.
|
||||
*/
|
||||
void av_hash_final_hex(struct AVHashContext *ctx, uint8_t *dst, int size);
|
||||
|
||||
/**
|
||||
* Finalize a hash context and compute the actual hash value as a base64 string.
|
||||
* The string is always 0-terminated.
|
||||
* If size is smaller than AV_BASE64_SIZE(hash_size), the base64 string is
|
||||
* truncated.
|
||||
*/
|
||||
void av_hash_final_b64(struct AVHashContext *ctx, uint8_t *dst, int size);
|
||||
|
||||
/**
|
||||
* Free hash context.
|
||||
*/
|
||||
|
@ -56,7 +56,7 @@
|
||||
*/
|
||||
|
||||
#define LIBAVUTIL_VERSION_MAJOR 52
|
||||
#define LIBAVUTIL_VERSION_MINOR 79
|
||||
#define LIBAVUTIL_VERSION_MINOR 80
|
||||
#define LIBAVUTIL_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
|
||||
|
@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libavutil/avstring.h"
|
||||
#include "libavutil/error.h"
|
||||
#include "libavutil/hash.h"
|
||||
#include "libavutil/mem.h"
|
||||
@ -40,14 +41,14 @@
|
||||
#define SIZE 65536
|
||||
|
||||
static struct AVHashContext *hash;
|
||||
static uint8_t *res;
|
||||
static int out_b64;
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
int i = 0;
|
||||
const char *name;
|
||||
|
||||
printf("usage: ffhash [algorithm] [input]...\n");
|
||||
printf("usage: ffhash [b64:]algorithm [input]...\n");
|
||||
printf("Supported hash algorithms:");
|
||||
do {
|
||||
name = av_hash_names(i);
|
||||
@ -60,12 +61,16 @@ static void usage(void)
|
||||
|
||||
static void finish(void)
|
||||
{
|
||||
int i, len = av_hash_get_size(hash);
|
||||
char res[2 * AV_HASH_MAX_SIZE + 4];
|
||||
|
||||
printf("%s=0x", av_hash_get_name(hash));
|
||||
av_hash_final(hash, res);
|
||||
for (i = 0; i < len; i++)
|
||||
printf("%02x", res[i]);
|
||||
printf("%s=", av_hash_get_name(hash));
|
||||
if (out_b64) {
|
||||
av_hash_final_b64(hash, res, sizeof(res));
|
||||
printf("b64:%s", res);
|
||||
} else {
|
||||
av_hash_final_hex(hash, res, sizeof(res));
|
||||
printf("0x%s", res);
|
||||
}
|
||||
}
|
||||
|
||||
static int check(char *file)
|
||||
@ -113,16 +118,19 @@ int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
const char *hash_name;
|
||||
|
||||
if (argc == 1) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ret = av_hash_alloc(&hash, argv[1])) < 0) {
|
||||
hash_name = argv[1];
|
||||
out_b64 = av_strstart(hash_name, "b64:", &hash_name);
|
||||
if ((ret = av_hash_alloc(&hash, hash_name)) < 0) {
|
||||
switch(ret) {
|
||||
case AVERROR(EINVAL):
|
||||
printf("Invalid hash type: %s\n", argv[1]);
|
||||
printf("Invalid hash type: %s\n", hash_name);
|
||||
break;
|
||||
case AVERROR(ENOMEM):
|
||||
printf("%s\n", strerror(errno));
|
||||
@ -130,11 +138,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
res = av_malloc(av_hash_get_size(hash));
|
||||
if (!res) {
|
||||
printf("%s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 2; i < argc; i++)
|
||||
ret |= check(argv[i]);
|
||||
@ -143,7 +146,6 @@ int main(int argc, char **argv)
|
||||
ret |= check(NULL);
|
||||
|
||||
av_hash_freep(&hash);
|
||||
av_freep(&res);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ known_AV_CODEC_ID_NONE=1
|
||||
known_AV_CODEC_ID_FIRST_AUDIO=1
|
||||
known_AV_CODEC_ID_FIRST_SUBTITLE=1
|
||||
known_AV_CODEC_ID_FIRST_UNKNOWN=1
|
||||
known_AV_CODEC_ID_TTF=1
|
||||
known_AV_CODEC_ID_PROBE=1
|
||||
known_AV_CODEC_ID_MPEG2TS=1
|
||||
known_AV_CODEC_ID_MPEG4SYSTEMS=1
|
||||
|
Loading…
x
Reference in New Issue
Block a user