[FFmpeg-devel] [PATCHv2] ffprobe: add support for subtitle frames
Stefano Sabatini
stefasab at gmail.com
Sun Nov 24 21:55:42 CET 2013
On date Sunday 2013-11-24 15:09:52 +0100, Marton Balint encoded:
> Signed-off-by: Marton Balint <cus at passwd.hu>
> ---
> doc/ffprobe.texi | 6 +++---
> doc/ffprobe.xsd | 15 ++++++++++++++-
> ffprobe.c | 41 +++++++++++++++++++++++++++++++++++++++--
> 3 files changed, 56 insertions(+), 6 deletions(-)
>
> diff --git a/doc/ffprobe.texi b/doc/ffprobe.texi
> index 2e9bfee..75d1e72 100644
> --- a/doc/ffprobe.texi
> +++ b/doc/ffprobe.texi
> @@ -197,11 +197,11 @@ The information for each single packet is printed within a dedicated
> section with name "PACKET".
>
> @item -show_frames
> -Show information about each frame contained in the input multimedia
> -stream.
> +Show information about each frame and subtitle 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".
>
> @item -show_streams
> Show information about each media stream contained in the input
> diff --git a/doc/ffprobe.xsd b/doc/ffprobe.xsd
> index 6a48ff4..cc3d1b6 100644
> --- a/doc/ffprobe.xsd
> +++ b/doc/ffprobe.xsd
> @@ -28,7 +28,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>
>
> @@ -82,6 +85,16 @@
> <xsd:attribute name="repeat_pict" type="xsd:int" />
> </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:sequence>
> <xsd:element name="stream" type="ffprobe:streamType" minOccurs="0" maxOccurs="unbounded"/>
> diff --git a/ffprobe.c b/ffprobe.c
> index ef4ccaf..75c3c5d 100644
> --- a/ffprobe.c
> +++ b/ffprobe.c
> @@ -135,6 +135,7 @@ typedef enum {
> SECTION_ID_STREAM_DISPOSITION,
> SECTION_ID_STREAMS,
> SECTION_ID_STREAM_TAGS,
> + SECTION_ID_SUBTITLE,
> } SectionID;
>
> static struct section sections[] = {
> @@ -144,7 +145,7 @@ static struct section sections[] = {
> [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, -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_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 } },
> @@ -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_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_SUBTITLE] = { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } },
> };
>
> static const OptionDef *options;
> @@ -1676,6 +1678,30 @@ static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pk
> fflush(stdout);
> }
>
> +static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream,
> + AVFormatContext *fmt_ctx)
nit++: weird indent
> +{
> + AVBPrint pbuf;
> + AVRational tb = (AVRational){1, AV_TIME_BASE};
> +
> + 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, &tb);
&AV_TIME_BASE_Q should also work
> + 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,
> AVFormatContext *fmt_ctx)
> {
> @@ -1752,6 +1778,7 @@ static av_always_inline int process_frame(WriterContext *w,
> AVFrame *frame, AVPacket *pkt)
> {
> AVCodecContext *dec_ctx = fmt_ctx->streams[pkt->stream_index]->codec;
> + AVSubtitle sub;
> int ret = 0, got_frame = 0;
>
> avcodec_get_frame_defaults(frame);
> @@ -1764,6 +1791,10 @@ static av_always_inline int process_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, &sub, &got_frame, pkt);
> + break;
> }
> }
>
> @@ -1773,9 +1804,15 @@ static av_always_inline int process_frame(WriterContext *w,
> pkt->data += ret;
> pkt->size -= ret;
> if (got_frame) {
> + int is_sub = (dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE);
> nb_streams_frames[pkt->stream_index]++;
> 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);
Looks good otherwise, thanks. I'll push with the fixes if there are no
more comments.
--
FFmpeg = Fanciful & Fundamentalist Majestic Power Encoding/decoding Geisha
More information about the ffmpeg-devel
mailing list