[FFmpeg-devel] [PATCH] ffprobe: decode and dump subtitles.
Nicolas George
nicolas.george at normalesup.org
Tue Jul 24 18:35:56 CEST 2012
Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
doc/ffprobe.texi | 2 +-
doc/ffprobe.xsd | 33 ++++++++++++++++++++++++-
ffprobe.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 98 insertions(+), 7 deletions(-)
diff --git a/doc/ffprobe.texi b/doc/ffprobe.texi
index cbe48a7..2fa2cdf 100644
--- a/doc/ffprobe.texi
+++ b/doc/ffprobe.texi
@@ -130,7 +130,7 @@ Show information about each frame contained in the input multimedia
stream.
The information for each single frame is printed within a dedicated
-section with name "FRAME".
+section with name "FRAME", or "SUBTITLE" for subtitles.
@item -show_streams
Show information about each media stream contained in the input
diff --git a/doc/ffprobe.xsd b/doc/ffprobe.xsd
index 3a4a8cc..254c801 100644
--- a/doc/ffprobe.xsd
+++ b/doc/ffprobe.xsd
@@ -26,7 +26,10 @@
<xsd:complexType name="framesType">
<xsd:sequence>
- <xsd:element name="frame" type="ffprobe:frameType" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="frame" type="ffprobe:frameType" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="subtitle" type="ffprobe:subtitleType" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:choice>
</xsd:sequence>
</xsd:complexType>
@@ -77,6 +80,34 @@
<xsd:attribute name="reference" type="xsd:int" />
</xsd:complexType>
+ <xsd:complexType name="subtitleType">
+ <xsd:sequence>
+ <xsd:element name="subtitle_header" type="ffprobe:subtitleHeaderType" minOccurs="1" maxOccurs="1"/>
+ <xsd:element name="subtitle_rectangle" type="ffprobe:subtitleRectangleType" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="subtitleHeaderType">
+ <xsd:attribute name="format" type="xsd:int" use="required"/>
+ <xsd:attribute name="start_display_time" type="xsd:int" use="required"/>
+ <xsd:attribute name="end_display_time" type="xsd:int" />
+ <xsd:attribute name="pts" type="xsd:long" />
+ <xsd:attribute name="pts_time" type="xsd:float"/>
+ <xsd:attribute name="pkt_pts" type="xsd:long" />
+ <xsd:attribute name="pkt_pts_time" type="xsd:float"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="subtitleRectangleType">
+ <xsd:attribute name="type" type="xsd:string" use="required"/>
+ <xsd:attribute name="x" type="xsd:int"/>
+ <xsd:attribute name="y" type="xsd:int" />
+ <xsd:attribute name="w" type="xsd:int" />
+ <xsd:attribute name="h" type="xsd:int" />
+ <xsd:attribute name="text_len" type="xsd:int" />
+ <xsd:attribute name="ass_len" type="xsd:int" />
+ <xsd:attribute name="forced" type="xsd:int" />
+ </xsd:complexType>
+
<xsd:complexType name="streamsType">
<xsd:sequence>
<xsd:element name="stream" type="ffprobe:streamType" minOccurs="0" maxOccurs="unbounded"/>
diff --git a/ffprobe.c b/ffprobe.c
index 531cea2..d7639c6 100644
--- a/ffprobe.c
+++ b/ffprobe.c
@@ -263,6 +263,7 @@ static inline void writer_print_chapter_header(WriterContext *wctx,
wctx->nb_section_packet_frame = 0;
wctx->is_packets_and_frames = !strcmp(chapter, "packets_and_frames");
wctx->multiple_sections = !strcmp(chapter, "packets") || !strcmp(chapter, "frames" ) ||
+ !strcmp(chapter, "subtitle") ||
wctx->is_packets_and_frames ||
!strcmp(chapter, "streams") || !strcmp(chapter, "library_versions");
wctx->is_fmt_chapter = !strcmp(chapter, "format");
@@ -1653,12 +1654,65 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream)
fflush(stdout);
}
+static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVPacket *pkt,
+ AVStream *stream)
+{
+ AVRational tb = AV_TIME_BASE_Q;
+ unsigned i;
+ static const char *const type_map[] = {
+ [SUBTITLE_NONE] = "none",
+ [SUBTITLE_BITMAP] = "bitmap",
+ [SUBTITLE_TEXT] = "text",
+ [SUBTITLE_ASS] = "ass",
+ };
+
+ writer_print_chapter_header(w, "subtitle");
+
+ print_section_header("subtitle_header");
+ print_int ("format", sub->format); /* TODO decode */
+ print_int ("start_display_time", sub->start_display_time);
+ print_int ("end_display_time", sub->end_display_time);
+ print_ts ("pts", sub->pts);
+ print_time("pts_time", sub->pts, &tb);
+ print_ts ("pkt_pts", pkt->pts);
+ print_time("pkt_pts_time", pkt->pts, &stream->time_base);
+ print_section_footer("subtitle");
+
+ for (i = 0; i < sub->num_rects; i++) {
+ AVSubtitleRect *r = sub->rects[i];
+ print_section_header("subtitle_rectangle");
+ print_str("type", (unsigned)r->type < FF_ARRAY_ELEMS(type_map) ?
+ type_map[r->type] : "unknown");
+ if (r->type == SUBTITLE_BITMAP) {
+ print_int("x", r->x);
+ print_int("y", r->y);
+ print_int("w", r->w);
+ print_int("h", r->h);
+ }
+ if (r->text)
+ print_int("text_len", strlen(r->text));
+ else
+ print_str_opt("text_len", "N/A");
+ if (r->ass)
+ print_int("ass_len", strlen(r->ass));
+ else
+ print_str_opt("ass_len", "N/A");
+ print_int("forced", r->forced);
+ print_section_footer("subtitle_rectangle");
+
+ }
+
+ writer_print_chapter_footer(w, "subtitle");
+ fflush(stdout);
+}
+
static av_always_inline int process_decoded_frame(WriterContext *w,
AVFormatContext *fmt_ctx,
AVFrame *frame, AVPacket *pkt)
{
AVCodecContext *dec_ctx = fmt_ctx->streams[pkt->stream_index]->codec;
- int ret = 0, got_frame = 0;
+ int ret = 0, got_frame = 0, got_sub = 0;
+ AVSubtitle subtitle;
avcodec_get_frame_defaults(frame);
if (dec_ctx->codec) {
@@ -1672,6 +1726,10 @@ static av_always_inline int process_decoded_frame(WriterContext *w,
case AVMEDIA_TYPE_AUDIO:
ret = avcodec_decode_audio4(dec_ctx, frame, &got_frame, pkt);
break;
+
+ case AVMEDIA_TYPE_SUBTITLE:
+ ret = avcodec_decode_subtitle2(dec_ctx, &subtitle, &got_sub, pkt);
+ break;
}
}
@@ -1679,10 +1737,12 @@ static av_always_inline int process_decoded_frame(WriterContext *w,
return ret;
pkt->data += ret;
pkt->size -= ret;
- if (got_frame) {
- nb_streams_frames[pkt->stream_index]++;
- if (do_show_frames)
- show_frame(w, frame, fmt_ctx->streams[pkt->stream_index]);
+ nb_streams_frames[pkt->stream_index] += got_frame || got_sub;
+ if (do_show_frames) {
+ if (got_frame)
+ show_frame(w, frame, fmt_ctx->streams[pkt->stream_index]);
+ if (got_sub)
+ show_subtitle(w, &subtitle, pkt, fmt_ctx->streams[pkt->stream_index]);
}
return got_frame;
}
--
1.7.10.4
More information about the ffmpeg-devel
mailing list