Commit a0286035 authored by Marton Balint's avatar Marton Balint Committed by Stefano Sabatini

ffprobe: add support for subtitle frames

Signed-off-by: 's avatarMarton Balint <cus@passwd.hu>
Signed-off-by: 's avatarStefano Sabatini <stefasab@gmail.com>
parent c0f2e071
...@@ -197,11 +197,11 @@ The information for each single packet is printed within a dedicated ...@@ -197,11 +197,11 @@ The information for each single packet is printed within a dedicated
section with name "PACKET". section with name "PACKET".
@item -show_frames @item -show_frames
Show information about each frame contained in the input multimedia Show information about each frame and subtitle contained in the input
stream. multimedia stream.
The information for each single frame is printed within a dedicated The information for each single frame is printed within a dedicated
section with name "FRAME". section with name "FRAME" or "SUBTITLE".
@item -show_streams @item -show_streams
Show information about each media stream contained in the input Show information about each media stream contained in the input
......
...@@ -28,7 +28,10 @@ ...@@ -28,7 +28,10 @@
<xsd:complexType name="framesType"> <xsd:complexType name="framesType">
<xsd:sequence> <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:sequence>
</xsd:complexType> </xsd:complexType>
...@@ -82,6 +85,16 @@ ...@@ -82,6 +85,16 @@
<xsd:attribute name="repeat_pict" type="xsd:int" /> <xsd:attribute name="repeat_pict" type="xsd:int" />
</xsd:complexType> </xsd:complexType>
<xsd:complexType name="subtitleType">
<xsd:attribute name="media_type" type="xsd:string" fixed="subtitle" use="required"/>
<xsd:attribute name="pts" type="xsd:long" />
<xsd:attribute name="pts_time" type="xsd:float"/>
<xsd:attribute name="format" type="xsd:int" />
<xsd:attribute name="start_display_time" type="xsd:int" />
<xsd:attribute name="end_display_time" type="xsd:int" />
<xsd:attribute name="num_rects" type="xsd:int" />
</xsd:complexType>
<xsd:complexType name="streamsType"> <xsd:complexType name="streamsType">
<xsd:sequence> <xsd:sequence>
<xsd:element name="stream" type="ffprobe:streamType" minOccurs="0" maxOccurs="unbounded"/> <xsd:element name="stream" type="ffprobe:streamType" minOccurs="0" maxOccurs="unbounded"/>
......
...@@ -135,6 +135,7 @@ typedef enum { ...@@ -135,6 +135,7 @@ typedef enum {
SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_DISPOSITION,
SECTION_ID_STREAMS, SECTION_ID_STREAMS,
SECTION_ID_STREAM_TAGS, SECTION_ID_STREAM_TAGS,
SECTION_ID_SUBTITLE,
} SectionID; } SectionID;
static struct section sections[] = { static struct section sections[] = {
...@@ -144,7 +145,7 @@ static struct section sections[] = { ...@@ -144,7 +145,7 @@ static struct section sections[] = {
[SECTION_ID_ERROR] = { SECTION_ID_ERROR, "error", 0, { -1 } }, [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] = { 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_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, -1 } }, [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, -1 } }, [SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, -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_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
[SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } }, [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
...@@ -167,6 +168,7 @@ static struct section sections[] = { ...@@ -167,6 +168,7 @@ static struct section sections[] = {
[SECTION_ID_STREAM] = { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, -1 } }, [SECTION_ID_STREAM] = { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, -1 } },
[SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" }, [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_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
[SECTION_ID_SUBTITLE] = { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } },
}; };
static const OptionDef *options; static const OptionDef *options;
...@@ -1675,6 +1677,29 @@ static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pk ...@@ -1675,6 +1677,29 @@ static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pk
fflush(stdout); fflush(stdout);
} }
static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream,
AVFormatContext *fmt_ctx)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
writer_print_section_header(w, SECTION_ID_SUBTITLE);
print_str ("media_type", "subtitle");
print_ts ("pts", sub->pts);
print_time("pts_time", sub->pts, &AV_TIME_BASE_Q);
print_int ("format", sub->format);
print_int ("start_display_time", sub->start_display_time);
print_int ("end_display_time", sub->end_display_time);
print_int ("num_rects", sub->num_rects);
writer_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
AVFormatContext *fmt_ctx) AVFormatContext *fmt_ctx)
{ {
...@@ -1751,6 +1776,7 @@ static av_always_inline int process_frame(WriterContext *w, ...@@ -1751,6 +1776,7 @@ static av_always_inline int process_frame(WriterContext *w,
AVFrame *frame, AVPacket *pkt) AVFrame *frame, AVPacket *pkt)
{ {
AVCodecContext *dec_ctx = fmt_ctx->streams[pkt->stream_index]->codec; AVCodecContext *dec_ctx = fmt_ctx->streams[pkt->stream_index]->codec;
AVSubtitle sub;
int ret = 0, got_frame = 0; int ret = 0, got_frame = 0;
avcodec_get_frame_defaults(frame); avcodec_get_frame_defaults(frame);
...@@ -1763,6 +1789,10 @@ static av_always_inline int process_frame(WriterContext *w, ...@@ -1763,6 +1789,10 @@ static av_always_inline int process_frame(WriterContext *w,
case AVMEDIA_TYPE_AUDIO: case AVMEDIA_TYPE_AUDIO:
ret = avcodec_decode_audio4(dec_ctx, frame, &got_frame, pkt); ret = avcodec_decode_audio4(dec_ctx, frame, &got_frame, pkt);
break; break;
case AVMEDIA_TYPE_SUBTITLE:
ret = avcodec_decode_subtitle2(dec_ctx, &sub, &got_frame, pkt);
break;
} }
} }
...@@ -1772,9 +1802,15 @@ static av_always_inline int process_frame(WriterContext *w, ...@@ -1772,9 +1802,15 @@ static av_always_inline int process_frame(WriterContext *w,
pkt->data += ret; pkt->data += ret;
pkt->size -= ret; pkt->size -= ret;
if (got_frame) { if (got_frame) {
int is_sub = (dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE);
nb_streams_frames[pkt->stream_index]++; nb_streams_frames[pkt->stream_index]++;
if (do_show_frames) if (do_show_frames)
show_frame(w, frame, fmt_ctx->streams[pkt->stream_index], fmt_ctx); if (is_sub)
show_subtitle(w, &sub, fmt_ctx->streams[pkt->stream_index], fmt_ctx);
else
show_frame(w, frame, fmt_ctx->streams[pkt->stream_index], fmt_ctx);
if (is_sub)
avsubtitle_free(&sub);
} }
return got_frame; return got_frame;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment