3692 lines · 132.8 KB · C
RawDownload
/* * 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 "config.h"#include "libavutil/ffversion.h" #include <string.h> #include "libavformat/avformat.h"#include "libavcodec/avcodec.h"#include "libavutil/avassert.h"#include "libavutil/avstring.h"#include "libavutil/bprint.h"#include "libavutil/display.h"#include "libavutil/hash.h"#include "libavutil/mastering_display_metadata.h"#include "libavutil/opt.h"#include "libavutil/pixdesc.h"#include "libavutil/spherical.h"#include "libavutil/stereo3d.h"#include "libavutil/dict.h"#include "libavutil/intreadwrite.h"#include "libavutil/libm.h"#include "libavutil/parseutils.h"#include "libavutil/timecode.h"#include "libavutil/timestamp.h"#include "libavdevice/avdevice.h"#include "libswscale/swscale.h"#include "libswresample/swresample.h"#include "libpostproc/postprocess.h"#include "cmdutils.h" #include "libavutil/thread.h" #if !HAVE_THREADS#  ifdef pthread_mutex_lock#    undef pthread_mutex_lock#  endif#  define pthread_mutex_lock(a) do{}while(0)#  ifdef pthread_mutex_unlock#    undef pthread_mutex_unlock#  endif#  define pthread_mutex_unlock(a) do{}while(0)#endif typedef struct InputStream {    AVStream *st;     AVCodecContext *dec_ctx;} InputStream; typedef struct InputFile {    AVFormatContext *fmt_ctx;     InputStream *streams;    int       nb_streams;} InputFile; const char program_name[] = "ffprobe";const int program_birth_year = 2007; static int do_bitexact = 0;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_chapters = 0;static int do_show_error   = 0;static int do_show_format  = 0;static int do_show_frames  = 0;static int do_show_packets = 0;static int do_show_programs = 0;static int do_show_streams = 0;static int do_show_stream_disposition = 0;static int do_show_data    = 0;static int do_show_program_version  = 0;static int do_show_library_versions = 0;static int do_show_pixel_formats = 0;static int do_show_pixel_format_flags = 0;static int do_show_pixel_format_components = 0;static int do_show_log = 0; static int do_show_chapter_tags = 0;static int do_show_format_tags = 0;static int do_show_frame_tags = 0;static int do_show_program_tags = 0;static int do_show_stream_tags = 0;static int do_show_packet_tags = 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 char *print_format;static char *stream_specifier;static char *show_data_hash; typedef struct ReadInterval {    int id;             ///< identifier    int64_t start, end; ///< start, end in second/AV_TIME_BASE units    int has_start, has_end;    int start_is_offset, end_is_offset;    int duration_frames;} ReadInterval; static ReadInterval *read_intervals;static int read_intervals_nb = 0; static int find_stream_info  = 1; /* section structure definition */ #define SECTION_MAX_NB_CHILDREN 10 struct section {    int id;             ///< unique id identifying a section    const char *name; #define SECTION_FLAG_IS_WRAPPER      1 ///< the section only contains other sections, but has no data at its own level#define SECTION_FLAG_IS_ARRAY        2 ///< the section contains an array of elements of the same type#define SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.                                           ///  For these sections the element_name field is mandatory.    int flags;    int children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1    const char *element_name; ///< name of the contained element, if provided    const char *unique_name;  ///< unique section name, in case the name is ambiguous    AVDictionary *entries_to_show;    int show_all_entries;}; typedef enum {    SECTION_ID_NONE = -1,    SECTION_ID_CHAPTER,    SECTION_ID_CHAPTER_TAGS,    SECTION_ID_CHAPTERS,    SECTION_ID_ERROR,    SECTION_ID_FORMAT,    SECTION_ID_FORMAT_TAGS,    SECTION_ID_FRAME,    SECTION_ID_FRAMES,    SECTION_ID_FRAME_TAGS,    SECTION_ID_FRAME_SIDE_DATA_LIST,    SECTION_ID_FRAME_SIDE_DATA,    SECTION_ID_FRAME_LOG,    SECTION_ID_FRAME_LOGS,    SECTION_ID_LIBRARY_VERSION,    SECTION_ID_LIBRARY_VERSIONS,    SECTION_ID_PACKET,    SECTION_ID_PACKET_TAGS,    SECTION_ID_PACKETS,    SECTION_ID_PACKETS_AND_FRAMES,    SECTION_ID_PACKET_SIDE_DATA_LIST,    SECTION_ID_PACKET_SIDE_DATA,    SECTION_ID_PIXEL_FORMAT,    SECTION_ID_PIXEL_FORMAT_FLAGS,    SECTION_ID_PIXEL_FORMAT_COMPONENT,    SECTION_ID_PIXEL_FORMAT_COMPONENTS,    SECTION_ID_PIXEL_FORMATS,    SECTION_ID_PROGRAM_STREAM_DISPOSITION,    SECTION_ID_PROGRAM_STREAM_TAGS,    SECTION_ID_PROGRAM,    SECTION_ID_PROGRAM_STREAMS,    SECTION_ID_PROGRAM_STREAM,    SECTION_ID_PROGRAM_TAGS,    SECTION_ID_PROGRAM_VERSION,    SECTION_ID_PROGRAMS,    SECTION_ID_ROOT,    SECTION_ID_STREAM,    SECTION_ID_STREAM_DISPOSITION,    SECTION_ID_STREAMS,    SECTION_ID_STREAM_TAGS,    SECTION_ID_STREAM_SIDE_DATA_LIST,    SECTION_ID_STREAM_SIDE_DATA,    SECTION_ID_SUBTITLE,} SectionID; static struct section sections[] = {    [SECTION_ID_CHAPTERS] =           { SECTION_ID_CHAPTERS, "chapters", SECTION_FLAG_IS_ARRAY, { SECTION_ID_CHAPTER, -1 } },    [SECTION_ID_CHAPTER] =            { SECTION_ID_CHAPTER, "chapter", 0, { SECTION_ID_CHAPTER_TAGS, -1 } },    [SECTION_ID_CHAPTER_TAGS] =       { SECTION_ID_CHAPTER_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "chapter_tags" },    [SECTION_ID_ERROR] =              { SECTION_ID_ERROR, "error", 0, { -1 } },    [SECTION_ID_FORMAT] =             { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } },    [SECTION_ID_FORMAT_TAGS] =        { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },    [SECTION_ID_FRAMES] =             { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } },    [SECTION_ID_FRAME] =              { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_LOGS, -1 } },    [SECTION_ID_FRAME_TAGS] =         { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },    [SECTION_ID_FRAME_SIDE_DATA_LIST] ={ SECTION_ID_FRAME_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "frame_side_data_list" },    [SECTION_ID_FRAME_SIDE_DATA] =     { SECTION_ID_FRAME_SIDE_DATA, "side_data", 0, { -1 } },    [SECTION_ID_FRAME_LOGS] =         { SECTION_ID_FRAME_LOGS, "logs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } },    [SECTION_ID_FRAME_LOG] =          { SECTION_ID_FRAME_LOG, "log", 0, { -1 },  },    [SECTION_ID_LIBRARY_VERSIONS] =   { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },    [SECTION_ID_LIBRARY_VERSION] =    { SECTION_ID_LIBRARY_VERSION, "library_version", 0, { -1 } },    [SECTION_ID_PACKETS] =            { SECTION_ID_PACKETS, "packets", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },    [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },    [SECTION_ID_PACKET] =             { SECTION_ID_PACKET, "packet", 0, { SECTION_ID_PACKET_TAGS, SECTION_ID_PACKET_SIDE_DATA_LIST, -1 } },    [SECTION_ID_PACKET_TAGS] =        { SECTION_ID_PACKET_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" },    [SECTION_ID_PACKET_SIDE_DATA_LIST] ={ SECTION_ID_PACKET_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "packet_side_data_list" },    [SECTION_ID_PACKET_SIDE_DATA] =     { SECTION_ID_PACKET_SIDE_DATA, "side_data", 0, { -1 } },    [SECTION_ID_PIXEL_FORMATS] =      { SECTION_ID_PIXEL_FORMATS, "pixel_formats", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PIXEL_FORMAT, -1 } },    [SECTION_ID_PIXEL_FORMAT] =       { SECTION_ID_PIXEL_FORMAT, "pixel_format", 0, { SECTION_ID_PIXEL_FORMAT_FLAGS, SECTION_ID_PIXEL_FORMAT_COMPONENTS, -1 } },    [SECTION_ID_PIXEL_FORMAT_FLAGS] = { SECTION_ID_PIXEL_FORMAT_FLAGS, "flags", 0, { -1 }, .unique_name = "pixel_format_flags" },    [SECTION_ID_PIXEL_FORMAT_COMPONENTS] = { SECTION_ID_PIXEL_FORMAT_COMPONENTS, "components", SECTION_FLAG_IS_ARRAY, {SECTION_ID_PIXEL_FORMAT_COMPONENT, -1 }, .unique_name = "pixel_format_components" },    [SECTION_ID_PIXEL_FORMAT_COMPONENT]  = { SECTION_ID_PIXEL_FORMAT_COMPONENT, "component", 0, { -1 } },    [SECTION_ID_PROGRAM_STREAM_DISPOSITION] = { SECTION_ID_PROGRAM_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "program_stream_disposition" },    [SECTION_ID_PROGRAM_STREAM_TAGS] =        { SECTION_ID_PROGRAM_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_stream_tags" },    [SECTION_ID_PROGRAM] =                    { SECTION_ID_PROGRAM, "program", 0, { SECTION_ID_PROGRAM_TAGS, SECTION_ID_PROGRAM_STREAMS, -1 } },    [SECTION_ID_PROGRAM_STREAMS] =            { SECTION_ID_PROGRAM_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM_STREAM, -1 }, .unique_name = "program_streams" },    [SECTION_ID_PROGRAM_STREAM] =             { SECTION_ID_PROGRAM_STREAM, "stream", 0, { SECTION_ID_PROGRAM_STREAM_DISPOSITION, SECTION_ID_PROGRAM_STREAM_TAGS, -1 }, .unique_name = "program_stream" },    [SECTION_ID_PROGRAM_TAGS] =               { SECTION_ID_PROGRAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_tags" },    [SECTION_ID_PROGRAM_VERSION] =    { SECTION_ID_PROGRAM_VERSION, "program_version", 0, { -1 } },    [SECTION_ID_PROGRAMS] =                   { SECTION_ID_PROGRAMS, "programs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM, -1 } },    [SECTION_ID_ROOT] =               { SECTION_ID_ROOT, "root", SECTION_FLAG_IS_WRAPPER,                                        { SECTION_ID_CHAPTERS, SECTION_ID_FORMAT, SECTION_ID_FRAMES, SECTION_ID_PROGRAMS, SECTION_ID_STREAMS,                                          SECTION_ID_PACKETS, SECTION_ID_ERROR, SECTION_ID_PROGRAM_VERSION, SECTION_ID_LIBRARY_VERSIONS,                                          SECTION_ID_PIXEL_FORMATS, -1} },    [SECTION_ID_STREAMS] =            { SECTION_ID_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM, -1 } },    [SECTION_ID_STREAM] =             { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, SECTION_ID_STREAM_SIDE_DATA_LIST, -1 } },    [SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" },    [SECTION_ID_STREAM_TAGS] =        { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },    [SECTION_ID_STREAM_SIDE_DATA_LIST] ={ SECTION_ID_STREAM_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "stream_side_data_list" },    [SECTION_ID_STREAM_SIDE_DATA] =     { SECTION_ID_STREAM_SIDE_DATA, "side_data", 0, { -1 } },    [SECTION_ID_SUBTITLE] =           { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } },}; static const OptionDef *options; /* FFprobe context */static const char *input_filename;static AVInputFormat *iformat = NULL; static struct AVHashContext *hash; static const struct {    double bin_val;    double dec_val;    const char *bin_str;    const char *dec_str;} si_prefixes[] = {    { 1.0, 1.0, "", "" },    { 1.024e3, 1e3, "Ki", "K" },    { 1.048576e6, 1e6, "Mi", "M" },    { 1.073741824e9, 1e9, "Gi", "G" },    { 1.099511627776e12, 1e12, "Ti", "T" },    { 1.125899906842624e15, 1e15, "Pi", "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 int nb_streams;static uint64_t *nb_streams_packets;static uint64_t *nb_streams_frames;static int *selected_streams; #if HAVE_THREADSpthread_mutex_t log_mutex;#endiftypedef struct LogBuffer {    char *context_name;    int log_level;    char *log_message;    AVClassCategory category;    char *parent_name;    AVClassCategory parent_category;}LogBuffer; static LogBuffer *log_buffer;static int log_buffer_size; static void log_callback(void *ptr, int level, const char *fmt, va_list vl){    AVClass* avc = ptr ? *(AVClass **) ptr : NULL;    va_list vl2;    char line[1024];    static int print_prefix = 1;    void *new_log_buffer;     va_copy(vl2, vl);    av_log_default_callback(ptr, level, fmt, vl);    av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);    va_end(vl2); #if HAVE_THREADS    pthread_mutex_lock(&log_mutex);     new_log_buffer = av_realloc_array(log_buffer, log_buffer_size + 1, sizeof(*log_buffer));    if (new_log_buffer) {        char *msg;        int i;         log_buffer = new_log_buffer;        memset(&log_buffer[log_buffer_size], 0, sizeof(log_buffer[log_buffer_size]));        log_buffer[log_buffer_size].context_name= avc ? av_strdup(avc->item_name(ptr)) : NULL;        if (avc) {            if (avc->get_category) log_buffer[log_buffer_size].category = avc->get_category(ptr);            else                   log_buffer[log_buffer_size].category = avc->category;        }        log_buffer[log_buffer_size].log_level   = level;        msg = log_buffer[log_buffer_size].log_message = av_strdup(line);        for (i=strlen(msg) - 1; i>=0 && msg[i] == '\n'; i--) {            msg[i] = 0;        }        if (avc && avc->parent_log_context_offset) {            AVClass** parent = *(AVClass ***) (((uint8_t *) ptr) +                                   avc->parent_log_context_offset);            if (parent && *parent) {                log_buffer[log_buffer_size].parent_name = av_strdup((*parent)->item_name(parent));                log_buffer[log_buffer_size].parent_category =                    (*parent)->get_category ? (*parent)->get_category(parent) :(*parent)->category;            }        }        log_buffer_size ++;    }     pthread_mutex_unlock(&log_mutex);#endif} static void ffprobe_cleanup(int ret){    int i;    for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)        av_dict_free(&(sections[i].entries_to_show)); #if HAVE_THREADS    pthread_mutex_destroy(&log_mutex);#endif} 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;    long long int vali;    int show_float = 0;     if (uv.unit == unit_second_str) {        vald = uv.val.d;        show_float = 1;    } else {        vald = vali = uv.val.i;    }     if (uv.unit == unit_second_str && use_value_sexagesimal_format) {        double secs;        int hours, mins;        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 = "";         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(si_prefixes) - 1);                vald /= si_prefixes[index].bin_val;                prefix_string = si_prefixes[index].bin_str;            } else {                index = (long long int) (log10(vald)) / 3;                index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);                vald /= si_prefixes[index].dec_val;                prefix_string = si_prefixes[index].dec_str;            }            vali = vald;        }         if (show_float || (use_value_prefix && vald != (long long int)vald))            snprintf(buf, buf_size, "%f", vald);        else            snprintf(buf, buf_size, "%lld", vali);        av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || show_value_unit ? " " : "",                 prefix_string, show_value_unit ? uv.unit : "");    }     return buf;} /* 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 enum {    WRITER_STRING_VALIDATION_FAIL,    WRITER_STRING_VALIDATION_REPLACE,    WRITER_STRING_VALIDATION_IGNORE,    WRITER_STRING_VALIDATION_NB} StringValidation; typedef struct Writer {    const AVClass *priv_class;      ///< private class of the writer, if any    int priv_size;                  ///< private size for the writer context    const char *name;     int  (*init)  (WriterContext *wctx);    void (*uninit)(WriterContext *wctx);     void (*print_section_header)(WriterContext *wctx);    void (*print_section_footer)(WriterContext *wctx);    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 *);    int flags;                  ///< a combination or WRITER_FLAG_*} Writer; #define SECTION_MAX_NB_LEVELS 10 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     const struct section *sections; ///< array containing all sections    int nb_sections;                ///< number of sections     int level;                      ///< current level, starting from 0     /** number of the item printed in the given section, starting from 0 */    unsigned int nb_item[SECTION_MAX_NB_LEVELS];     /** section per each level */    const struct section *section[SECTION_MAX_NB_LEVELS];    AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]; ///< generic print buffer dedicated to each section,                                                  ///  used by various writers     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     int string_validation;    char *string_validation_replacement;    unsigned int string_validation_utf8_flags;}; static const char *writer_get_name(void *p){    WriterContext *wctx = p;    return wctx->writer->name;} #define OFFSET(x) offsetof(WriterContext, x) static const AVOption writer_options[] = {    { "string_validation", "set string validation mode",      OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },    { "sv", "set string validation mode",      OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },    { "ignore",  NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_IGNORE},  .unit = "sv" },    { "replace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_REPLACE}, .unit = "sv" },    { "fail",    NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_FAIL},    .unit = "sv" },    { "string_validation_replacement", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str=""}},    { "svr", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str="\xEF\xBF\xBD"}},    { NULL }}; static void *writer_child_next(void *obj, void *prev){    WriterContext *ctx = obj;    if (!prev && ctx->writer && ctx->writer->priv_class && ctx->priv)        return ctx->priv;    return NULL;

Lines 1–500 of 3692.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t