Newer
Older
/*
* Copyright (c) 2007-2010 Stefano Sabatini
*
* This file is part of FFmpeg.
*
* FFmpeg 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.
*
* FFmpeg 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 FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* simple media prober based on the FFmpeg libraries
*/
#include "version.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavutil/avstring.h"
#include "libavutil/dict.h"
#include "libavutil/libm.h"
#include "libavutil/timecode.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "libpostproc/postprocess.h"
static int do_count_frames = 0;
static int do_count_packets = 0;
static int do_read_frames = 0;
static int do_read_packets = 0;
static int do_show_error = 0;
static int do_show_frames = 0;
static AVDictionary *fmt_entries_to_show = NULL;
static int do_show_program_version = 0;
static int do_show_library_versions = 0;
static int show_value_unit = 0;
static int use_value_prefix = 0;
static int use_byte_value_binary_prefix = 0;
static int use_value_sexagesimal_format = 0;
static int show_private_data = 1;
static const OptionDef *options;
/* FFprobe context */
static const char *input_filename;
static AVInputFormat *iformat = NULL;
static const char *const binary_unit_prefixes [] = { "", "Ki", "Mi", "Gi", "Ti", "Pi" };
static const char *const decimal_unit_prefixes[] = { "", "K" , "M" , "G" , "T" , "P" };
static const char unit_second_str[] = "s" ;
static const char unit_hertz_str[] = "Hz" ;
static const char unit_byte_str[] = "byte" ;
static const char unit_bit_per_second_str[] = "bit/s";
static uint64_t *nb_streams_packets;
static uint64_t *nb_streams_frames;
av_dict_free(&fmt_entries_to_show);
struct unit_value {
union { double d; long long int i; } val;
const char *unit;
};
static char *value_string(char *buf, int buf_size, struct unit_value uv)
double vald;
int show_float = 0;
if (uv.unit == unit_second_str) {
vald = uv.val.d;
show_float = 1;
} else {
vald = uv.val.i;
}
if (uv.unit == unit_second_str && use_value_sexagesimal_format) {
secs = vald;
mins = (int)secs / 60;
secs = secs - mins * 60;
hours = mins / 60;
mins %= 60;
snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
} else {
const char *prefix_string = "";
Stefano Sabatini
committed
if (use_value_prefix && vald > 1) {
long long int index;
if (uv.unit == unit_byte_str && use_byte_value_binary_prefix) {
index = (long long int) (log2(vald)) / 10;
index = av_clip(index, 0, FF_ARRAY_ELEMS(binary_unit_prefixes) - 1);
vald /= pow(2, index * 10);
prefix_string = binary_unit_prefixes[index];
} else {
index = (long long int) (log10(vald)) / 3;
index = av_clip(index, 0, FF_ARRAY_ELEMS(decimal_unit_prefixes) - 1);
vald /= pow(10, index * 3);
prefix_string = decimal_unit_prefixes[index];
}
if (show_float || (use_value_prefix && vald != (long long int)vald))
l = snprintf(buf, buf_size, "%f", vald);
else
l = snprintf(buf, buf_size, "%lld", (long long int)vald);
snprintf(buf+l, buf_size-l, "%s%s%s", *prefix_string || show_value_unit ? " " : "",
prefix_string, show_value_unit ? uv.unit : "");
/* WRITERS API */
typedef struct WriterContext WriterContext;
#define WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS 1
#define WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER 2
typedef struct Writer {
int priv_size; ///< private size for the writer context
const char *name;
int (*init) (WriterContext *wctx, const char *args, void *opaque);
void (*uninit)(WriterContext *wctx);
void (*print_header)(WriterContext *ctx);
void (*print_footer)(WriterContext *ctx);
void (*print_chapter_header)(WriterContext *wctx, const char *);
void (*print_chapter_footer)(WriterContext *wctx, const char *);
void (*print_section_header)(WriterContext *wctx, const char *);
void (*print_section_footer)(WriterContext *wctx, const char *);
void (*print_integer) (WriterContext *wctx, const char *, long long int);
void (*print_rational) (WriterContext *wctx, AVRational *q, char *sep);
void (*print_string) (WriterContext *wctx, const char *, const char *);
void (*show_tags) (WriterContext *wctx, AVDictionary *dict);
int flags; ///< a combination or WRITER_FLAG_*
} Writer;
struct WriterContext {
const AVClass *class; ///< class of the writer
const Writer *writer; ///< the Writer of which this is an instance
char *name; ///< name of this writer instance
void *priv; ///< private data for use by the filter
unsigned int nb_item; ///< number of the item printed in the given section, starting at 0
unsigned int nb_section; ///< number of the section printed in the given section sequence, starting at 0
unsigned int nb_section_packet; ///< number of the packet section in case we are in "packets_and_frames" section
unsigned int nb_section_frame; ///< number of the frame section in case we are in "packets_and_frames" section
unsigned int nb_section_packet_frame; ///< nb_section_packet or nb_section_frame according if is_packets_and_frames
unsigned int nb_chapter; ///< number of the chapter, starting at 0
int multiple_sections; ///< tells if the current chapter can contain multiple sections
int is_fmt_chapter; ///< tells if the current chapter is "format", required by the print_format_entry option
int is_packets_and_frames; ///< tells if the current section is "packets_and_frames"
static const char *writer_get_name(void *p)
{
WriterContext *wctx = p;
return wctx->writer->name;
}
static const AVClass writer_class = {
"Writer",
Loading
Loading full blame...