2 * Various pretty-printing functions for use within FFmpeg
3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "libavutil/channel_layout.h"
26 #include "libavutil/display.h"
27 #include "libavutil/intreadwrite.h"
28 #include "libavutil/log.h"
29 #include "libavutil/mathematics.h"
30 #include "libavutil/avstring.h"
31 #include "libavutil/replaygain.h"
32 #include "libavutil/stereo3d.h"
36 #define HEXDUMP_PRINT(...) \
39 av_log(avcl, level, __VA_ARGS__); \
41 fprintf(f, __VA_ARGS__); \
44 static void hex_dump_internal(void *avcl
, FILE *f
, int level
,
45 const uint8_t *buf
, int size
)
49 for (i
= 0; i
< size
; i
+= 16) {
53 HEXDUMP_PRINT("%08x ", i
);
54 for (j
= 0; j
< 16; j
++) {
56 HEXDUMP_PRINT(" %02x", buf
[i
+ j
]);
61 for (j
= 0; j
< len
; j
++) {
63 if (c
< ' ' || c
> '~')
65 HEXDUMP_PRINT("%c", c
);
71 void av_hex_dump(FILE *f
, const uint8_t *buf
, int size
)
73 hex_dump_internal(NULL
, f
, 0, buf
, size
);
76 void av_hex_dump_log(void *avcl
, int level
, const uint8_t *buf
, int size
)
78 hex_dump_internal(avcl
, NULL
, level
, buf
, size
);
81 static void pkt_dump_internal(void *avcl
, FILE *f
, int level
, const AVPacket
*pkt
,
82 int dump_payload
, AVRational time_base
)
84 HEXDUMP_PRINT("stream #%d:\n", pkt
->stream_index
);
85 HEXDUMP_PRINT(" keyframe=%d\n", (pkt
->flags
& AV_PKT_FLAG_KEY
) != 0);
86 HEXDUMP_PRINT(" duration=%0.3f\n", pkt
->duration
* av_q2d(time_base
));
87 /* DTS is _always_ valid after av_read_frame() */
88 HEXDUMP_PRINT(" dts=");
89 if (pkt
->dts
== AV_NOPTS_VALUE
)
92 HEXDUMP_PRINT("%0.3f", pkt
->dts
* av_q2d(time_base
));
93 /* PTS may not be known if B-frames are present. */
94 HEXDUMP_PRINT(" pts=");
95 if (pkt
->pts
== AV_NOPTS_VALUE
)
98 HEXDUMP_PRINT("%0.3f", pkt
->pts
* av_q2d(time_base
));
100 HEXDUMP_PRINT(" size=%d\n", pkt
->size
);
102 av_hex_dump(f
, pkt
->data
, pkt
->size
);
105 void av_pkt_dump2(FILE *f
, const AVPacket
*pkt
, int dump_payload
, const AVStream
*st
)
107 pkt_dump_internal(NULL
, f
, 0, pkt
, dump_payload
, st
->time_base
);
110 void av_pkt_dump_log2(void *avcl
, int level
, const AVPacket
*pkt
, int dump_payload
,
113 pkt_dump_internal(avcl
, NULL
, level
, pkt
, dump_payload
, st
->time_base
);
117 static void print_fps(double d
, const char *postfix
)
119 uint64_t v
= lrintf(d
* 100);
121 av_log(NULL
, AV_LOG_INFO
, ", %3.2f %s", d
, postfix
);
122 else if (v
% (100 * 1000))
123 av_log(NULL
, AV_LOG_INFO
, ", %1.0f %s", d
, postfix
);
125 av_log(NULL
, AV_LOG_INFO
, ", %1.0fk %s", d
/ 1000, postfix
);
128 static void dump_metadata(void *ctx
, AVDictionary
*m
, const char *indent
)
130 if (m
&& !(av_dict_count(m
) == 1 && av_dict_get(m
, "language", NULL
, 0))) {
131 AVDictionaryEntry
*tag
= NULL
;
133 av_log(ctx
, AV_LOG_INFO
, "%sMetadata:\n", indent
);
134 while ((tag
= av_dict_get(m
, "", tag
, AV_DICT_IGNORE_SUFFIX
)))
135 if (strcmp("language", tag
->key
)) {
136 const char *p
= tag
->value
;
137 av_log(ctx
, AV_LOG_INFO
,
138 "%s %-16s: ", indent
, tag
->key
);
141 size_t len
= strcspn(p
, "\x8\xa\xb\xc\xd");
142 av_strlcpy(tmp
, p
, FFMIN(sizeof(tmp
), len
+1));
143 av_log(ctx
, AV_LOG_INFO
, "%s", tmp
);
145 if (*p
== 0xd) av_log(ctx
, AV_LOG_INFO
, " ");
146 if (*p
== 0xa) av_log(ctx
, AV_LOG_INFO
, "\n%s %-16s: ", indent
, "");
149 av_log(ctx
, AV_LOG_INFO
, "\n");
154 /* param change side data*/
155 static void dump_paramchange(void *ctx
, AVPacketSideData
*sd
)
158 const uint8_t *data
= sd
->data
;
159 uint32_t flags
, channels
, sample_rate
, width
, height
;
162 if (!data
|| sd
->size
< 4)
165 flags
= AV_RL32(data
);
169 if (flags
& AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT
) {
172 channels
= AV_RL32(data
);
175 av_log(ctx
, AV_LOG_INFO
, "channel count %"PRIu32
", ", channels
);
177 if (flags
& AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT
) {
180 layout
= AV_RL64(data
);
183 av_log(ctx
, AV_LOG_INFO
,
184 "channel layout: %s, ", av_get_channel_name(layout
));
186 if (flags
& AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE
) {
189 sample_rate
= AV_RL32(data
);
192 av_log(ctx
, AV_LOG_INFO
, "sample_rate %"PRIu32
", ", sample_rate
);
194 if (flags
& AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS
) {
197 width
= AV_RL32(data
);
200 height
= AV_RL32(data
);
203 av_log(ctx
, AV_LOG_INFO
, "width %"PRIu32
" height %"PRIu32
, width
, height
);
208 av_log(ctx
, AV_LOG_INFO
, "unknown param");
211 /* replaygain side data*/
212 static void print_gain(void *ctx
, const char *str
, int32_t gain
)
214 av_log(ctx
, AV_LOG_INFO
, "%s - ", str
);
215 if (gain
== INT32_MIN
)
216 av_log(ctx
, AV_LOG_INFO
, "unknown");
218 av_log(ctx
, AV_LOG_INFO
, "%f", gain
/ 100000.0f
);
219 av_log(ctx
, AV_LOG_INFO
, ", ");
222 static void print_peak(void *ctx
, const char *str
, uint32_t peak
)
224 av_log(ctx
, AV_LOG_INFO
, "%s - ", str
);
226 av_log(ctx
, AV_LOG_INFO
, "unknown");
228 av_log(ctx
, AV_LOG_INFO
, "%f", (float) peak
/ UINT32_MAX
);
229 av_log(ctx
, AV_LOG_INFO
, ", ");
232 static void dump_replaygain(void *ctx
, AVPacketSideData
*sd
)
236 if (sd
->size
< sizeof(*rg
)) {
237 av_log(ctx
, AV_LOG_INFO
, "invalid data");
240 rg
= (AVReplayGain
*)sd
->data
;
242 print_gain(ctx
, "track gain", rg
->track_gain
);
243 print_peak(ctx
, "track peak", rg
->track_peak
);
244 print_gain(ctx
, "album gain", rg
->album_gain
);
245 print_peak(ctx
, "album peak", rg
->album_peak
);
248 static void dump_stereo3d(void *ctx
, AVPacketSideData
*sd
)
252 if (sd
->size
< sizeof(*stereo
)) {
253 av_log(ctx
, AV_LOG_INFO
, "invalid data");
257 stereo
= (AVStereo3D
*)sd
->data
;
259 switch (stereo
->type
) {
261 av_log(ctx
, AV_LOG_INFO
, "2D");
263 case AV_STEREO3D_SIDEBYSIDE
:
264 av_log(ctx
, AV_LOG_INFO
, "side by side");
266 case AV_STEREO3D_TOPBOTTOM
:
267 av_log(ctx
, AV_LOG_INFO
, "top and bottom");
269 case AV_STEREO3D_FRAMESEQUENCE
:
270 av_log(ctx
, AV_LOG_INFO
, "frame alternate");
272 case AV_STEREO3D_CHECKERBOARD
:
273 av_log(ctx
, AV_LOG_INFO
, "checkerboard");
275 case AV_STEREO3D_LINES
:
276 av_log(ctx
, AV_LOG_INFO
, "interleaved lines");
278 case AV_STEREO3D_COLUMNS
:
279 av_log(ctx
, AV_LOG_INFO
, "interleaved columns");
281 case AV_STEREO3D_SIDEBYSIDE_QUINCUNX
:
282 av_log(ctx
, AV_LOG_INFO
, "side by side (quincunx subsampling)");
285 av_log(ctx
, AV_LOG_WARNING
, "unknown");
289 if (stereo
->flags
& AV_STEREO3D_FLAG_INVERT
)
290 av_log(ctx
, AV_LOG_INFO
, " (inverted)");
293 static void dump_sidedata(void *ctx
, AVStream
*st
, const char *indent
)
297 if (st
->nb_side_data
)
298 av_log(ctx
, AV_LOG_INFO
, "%sSide data:\n", indent
);
300 for (i
= 0; i
< st
->nb_side_data
; i
++) {
301 AVPacketSideData sd
= st
->side_data
[i
];
302 av_log(ctx
, AV_LOG_INFO
, "%s ", indent
);
305 case AV_PKT_DATA_PALETTE
:
306 av_log(ctx
, AV_LOG_INFO
, "palette");
308 case AV_PKT_DATA_NEW_EXTRADATA
:
309 av_log(ctx
, AV_LOG_INFO
, "new extradata");
311 case AV_PKT_DATA_PARAM_CHANGE
:
312 av_log(ctx
, AV_LOG_INFO
, "paramchange: ");
313 dump_paramchange(ctx
, &sd
);
315 case AV_PKT_DATA_H263_MB_INFO
:
316 av_log(ctx
, AV_LOG_INFO
, "h263 macroblock info");
318 case AV_PKT_DATA_REPLAYGAIN
:
319 av_log(ctx
, AV_LOG_INFO
, "replaygain: ");
320 dump_replaygain(ctx
, &sd
);
322 case AV_PKT_DATA_DISPLAYMATRIX
:
323 av_log(ctx
, AV_LOG_INFO
, "displaymatrix: rotation of %.2f degrees",
324 av_display_rotation_get((int32_t *)sd
.data
));
326 case AV_PKT_DATA_STEREO3D
:
327 av_log(ctx
, AV_LOG_INFO
, "stereo3d: ");
328 dump_stereo3d(ctx
, &sd
);
331 av_log(ctx
, AV_LOG_WARNING
,
332 "unknown side data type %d (%d bytes)", sd
.type
, sd
.size
);
336 av_log(ctx
, AV_LOG_INFO
, "\n");
340 /* "user interface" functions */
341 static void dump_stream_format(AVFormatContext
*ic
, int i
,
342 int index
, int is_output
)
345 int flags
= (is_output
? ic
->oformat
->flags
: ic
->iformat
->flags
);
346 AVStream
*st
= ic
->streams
[i
];
347 AVDictionaryEntry
*lang
= av_dict_get(st
->metadata
, "language", NULL
, 0);
349 avcodec_string(buf
, sizeof(buf
), st
->codec
, is_output
);
350 av_log(NULL
, AV_LOG_INFO
, " Stream #%d:%d", index
, i
);
352 /* the pid is an important information, so we display it */
353 /* XXX: add a generic system */
354 if (flags
& AVFMT_SHOW_IDS
)
355 av_log(NULL
, AV_LOG_INFO
, "[0x%x]", st
->id
);
357 av_log(NULL
, AV_LOG_INFO
, "(%s)", lang
->value
);
358 av_log(NULL
, AV_LOG_DEBUG
, ", %d, %d/%d", st
->codec_info_nb_frames
,
359 st
->time_base
.num
, st
->time_base
.den
);
360 av_log(NULL
, AV_LOG_INFO
, ": %s", buf
);
362 if (st
->sample_aspect_ratio
.num
&& // default
363 av_cmp_q(st
->sample_aspect_ratio
, st
->codec
->sample_aspect_ratio
)) {
364 AVRational display_aspect_ratio
;
365 av_reduce(&display_aspect_ratio
.num
, &display_aspect_ratio
.den
,
366 st
->codec
->width
* st
->sample_aspect_ratio
.num
,
367 st
->codec
->height
* st
->sample_aspect_ratio
.den
,
369 av_log(NULL
, AV_LOG_INFO
, ", SAR %d:%d DAR %d:%d",
370 st
->sample_aspect_ratio
.num
, st
->sample_aspect_ratio
.den
,
371 display_aspect_ratio
.num
, display_aspect_ratio
.den
);
374 if (st
->codec
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
375 if (st
->avg_frame_rate
.den
&& st
->avg_frame_rate
.num
)
376 print_fps(av_q2d(st
->avg_frame_rate
), "fps");
377 #if FF_API_R_FRAME_RATE
378 if (st
->r_frame_rate
.den
&& st
->r_frame_rate
.num
)
379 print_fps(av_q2d(st
->r_frame_rate
), "tbr");
381 if (st
->time_base
.den
&& st
->time_base
.num
)
382 print_fps(1 / av_q2d(st
->time_base
), "tbn");
383 if (st
->codec
->time_base
.den
&& st
->codec
->time_base
.num
)
384 print_fps(1 / av_q2d(st
->codec
->time_base
), "tbc");
387 if (st
->disposition
& AV_DISPOSITION_DEFAULT
)
388 av_log(NULL
, AV_LOG_INFO
, " (default)");
389 if (st
->disposition
& AV_DISPOSITION_DUB
)
390 av_log(NULL
, AV_LOG_INFO
, " (dub)");
391 if (st
->disposition
& AV_DISPOSITION_ORIGINAL
)
392 av_log(NULL
, AV_LOG_INFO
, " (original)");
393 if (st
->disposition
& AV_DISPOSITION_COMMENT
)
394 av_log(NULL
, AV_LOG_INFO
, " (comment)");
395 if (st
->disposition
& AV_DISPOSITION_LYRICS
)
396 av_log(NULL
, AV_LOG_INFO
, " (lyrics)");
397 if (st
->disposition
& AV_DISPOSITION_KARAOKE
)
398 av_log(NULL
, AV_LOG_INFO
, " (karaoke)");
399 if (st
->disposition
& AV_DISPOSITION_FORCED
)
400 av_log(NULL
, AV_LOG_INFO
, " (forced)");
401 if (st
->disposition
& AV_DISPOSITION_HEARING_IMPAIRED
)
402 av_log(NULL
, AV_LOG_INFO
, " (hearing impaired)");
403 if (st
->disposition
& AV_DISPOSITION_VISUAL_IMPAIRED
)
404 av_log(NULL
, AV_LOG_INFO
, " (visual impaired)");
405 if (st
->disposition
& AV_DISPOSITION_CLEAN_EFFECTS
)
406 av_log(NULL
, AV_LOG_INFO
, " (clean effects)");
407 av_log(NULL
, AV_LOG_INFO
, "\n");
409 dump_metadata(NULL
, st
->metadata
, " ");
411 dump_sidedata(NULL
, st
, " ");
414 void av_dump_format(AVFormatContext
*ic
, int index
,
415 const char *url
, int is_output
)
418 uint8_t *printed
= ic
->nb_streams
? av_mallocz(ic
->nb_streams
) : NULL
;
419 if (ic
->nb_streams
&& !printed
)
422 av_log(NULL
, AV_LOG_INFO
, "%s #%d, %s, %s '%s':\n",
423 is_output
? "Output" : "Input",
425 is_output
? ic
->oformat
->name
: ic
->iformat
->name
,
426 is_output
? "to" : "from", url
);
427 dump_metadata(NULL
, ic
->metadata
, " ");
430 av_log(NULL
, AV_LOG_INFO
, " Duration: ");
431 if (ic
->duration
!= AV_NOPTS_VALUE
) {
432 int hours
, mins
, secs
, us
;
433 int64_t duration
= ic
->duration
+ 5000;
434 secs
= duration
/ AV_TIME_BASE
;
435 us
= duration
% AV_TIME_BASE
;
440 av_log(NULL
, AV_LOG_INFO
, "%02d:%02d:%02d.%02d", hours
, mins
, secs
,
441 (100 * us
) / AV_TIME_BASE
);
443 av_log(NULL
, AV_LOG_INFO
, "N/A");
445 if (ic
->start_time
!= AV_NOPTS_VALUE
) {
447 av_log(NULL
, AV_LOG_INFO
, ", start: ");
448 secs
= ic
->start_time
/ AV_TIME_BASE
;
449 us
= abs(ic
->start_time
% AV_TIME_BASE
);
450 av_log(NULL
, AV_LOG_INFO
, "%d.%06d",
451 secs
, (int) av_rescale(us
, 1000000, AV_TIME_BASE
));
453 av_log(NULL
, AV_LOG_INFO
, ", bitrate: ");
455 av_log(NULL
, AV_LOG_INFO
, "%d kb/s", ic
->bit_rate
/ 1000);
457 av_log(NULL
, AV_LOG_INFO
, "N/A");
458 av_log(NULL
, AV_LOG_INFO
, "\n");
461 for (i
= 0; i
< ic
->nb_chapters
; i
++) {
462 AVChapter
*ch
= ic
->chapters
[i
];
463 av_log(NULL
, AV_LOG_INFO
, " Chapter #%d.%d: ", index
, i
);
464 av_log(NULL
, AV_LOG_INFO
,
465 "start %f, ", ch
->start
* av_q2d(ch
->time_base
));
466 av_log(NULL
, AV_LOG_INFO
,
467 "end %f\n", ch
->end
* av_q2d(ch
->time_base
));
469 dump_metadata(NULL
, ch
->metadata
, " ");
472 if (ic
->nb_programs
) {
474 for (j
= 0; j
< ic
->nb_programs
; j
++) {
475 AVDictionaryEntry
*name
= av_dict_get(ic
->programs
[j
]->metadata
,
477 av_log(NULL
, AV_LOG_INFO
, " Program %d %s\n", ic
->programs
[j
]->id
,
478 name
? name
->value
: "");
479 dump_metadata(NULL
, ic
->programs
[j
]->metadata
, " ");
480 for (k
= 0; k
< ic
->programs
[j
]->nb_stream_indexes
; k
++) {
481 dump_stream_format(ic
, ic
->programs
[j
]->stream_index
[k
],
483 printed
[ic
->programs
[j
]->stream_index
[k
]] = 1;
485 total
+= ic
->programs
[j
]->nb_stream_indexes
;
487 if (total
< ic
->nb_streams
)
488 av_log(NULL
, AV_LOG_INFO
, " No Program\n");
491 for (i
= 0; i
< ic
->nb_streams
; i
++)
493 dump_stream_format(ic
, i
, index
, is_output
);