Browse code

ffprobe: add support for subtitle frames

Signed-off-by: Marton Balint <cus@passwd.hu>
Signed-off-by: Stefano Sabatini <stefasab@gmail.com>

Marton Balint authored on 2013/11/24 23:09:52
Showing 3 changed files
... ...
@@ -197,11 +197,11 @@ The information for each single packet is printed within a dedicated
197 197
 section with name "PACKET".
198 198
 
199 199
 @item -show_frames
200
-Show information about each frame contained in the input multimedia
201
-stream.
200
+Show information about each frame and subtitle contained in the input
201
+multimedia stream.
202 202
 
203 203
 The information for each single frame is printed within a dedicated
204
-section with name "FRAME".
204
+section with name "FRAME" or "SUBTITLE".
205 205
 
206 206
 @item -show_streams
207 207
 Show information about each media stream contained in the input
... ...
@@ -28,7 +28,10 @@
28 28
 
29 29
     <xsd:complexType name="framesType">
30 30
         <xsd:sequence>
31
-            <xsd:element name="frame" type="ffprobe:frameType" minOccurs="0" maxOccurs="unbounded"/>
31
+            <xsd:choice minOccurs="0" maxOccurs="unbounded">
32
+                <xsd:element name="frame" type="ffprobe:frameType" minOccurs="0" maxOccurs="unbounded"/>
33
+                <xsd:element name="subtitle" type="ffprobe:subtitleType" minOccurs="0" maxOccurs="unbounded"/>
34
+            </xsd:choice>
32 35
         </xsd:sequence>
33 36
     </xsd:complexType>
34 37
 
... ...
@@ -82,6 +85,16 @@
82 82
       <xsd:attribute name="repeat_pict"            type="xsd:int"   />
83 83
     </xsd:complexType>
84 84
 
85
+    <xsd:complexType name="subtitleType">
86
+      <xsd:attribute name="media_type"         type="xsd:string" fixed="subtitle" use="required"/>
87
+      <xsd:attribute name="pts"                type="xsd:long" />
88
+      <xsd:attribute name="pts_time"           type="xsd:float"/>
89
+      <xsd:attribute name="format"             type="xsd:int"  />
90
+      <xsd:attribute name="start_display_time" type="xsd:int"  />
91
+      <xsd:attribute name="end_display_time"   type="xsd:int"  />
92
+      <xsd:attribute name="num_rects"          type="xsd:int"  />
93
+    </xsd:complexType>
94
+
85 95
     <xsd:complexType name="streamsType">
86 96
         <xsd:sequence>
87 97
             <xsd:element name="stream" type="ffprobe:streamType" minOccurs="0" maxOccurs="unbounded"/>
... ...
@@ -135,6 +135,7 @@ typedef enum {
135 135
     SECTION_ID_STREAM_DISPOSITION,
136 136
     SECTION_ID_STREAMS,
137 137
     SECTION_ID_STREAM_TAGS,
138
+    SECTION_ID_SUBTITLE,
138 139
 } SectionID;
139 140
 
140 141
 static struct section sections[] = {
... ...
@@ -144,7 +145,7 @@ static struct section sections[] = {
144 144
     [SECTION_ID_ERROR] =              { SECTION_ID_ERROR, "error", 0, { -1 } },
145 145
     [SECTION_ID_FORMAT] =             { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } },
146 146
     [SECTION_ID_FORMAT_TAGS] =        { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
147
-    [SECTION_ID_FRAMES] =             { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, -1 } },
147
+    [SECTION_ID_FRAMES] =             { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } },
148 148
     [SECTION_ID_FRAME] =              { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, -1 } },
149 149
     [SECTION_ID_FRAME_TAGS] =         { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
150 150
     [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 167
     [SECTION_ID_STREAM] =             { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, -1 } },
168 168
     [SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" },
169 169
     [SECTION_ID_STREAM_TAGS] =        { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
170
+    [SECTION_ID_SUBTITLE] =           { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } },
170 171
 };
171 172
 
172 173
 static const OptionDef *options;
... ...
@@ -1675,6 +1677,29 @@ static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pk
1675 1675
     fflush(stdout);
1676 1676
 }
1677 1677
 
1678
+static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream,
1679
+                          AVFormatContext *fmt_ctx)
1680
+{
1681
+    AVBPrint pbuf;
1682
+
1683
+    av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
1684
+
1685
+    writer_print_section_header(w, SECTION_ID_SUBTITLE);
1686
+
1687
+    print_str ("media_type",         "subtitle");
1688
+    print_ts  ("pts",                 sub->pts);
1689
+    print_time("pts_time",            sub->pts, &AV_TIME_BASE_Q);
1690
+    print_int ("format",              sub->format);
1691
+    print_int ("start_display_time",  sub->start_display_time);
1692
+    print_int ("end_display_time",    sub->end_display_time);
1693
+    print_int ("num_rects",           sub->num_rects);
1694
+
1695
+    writer_print_section_footer(w);
1696
+
1697
+    av_bprint_finalize(&pbuf, NULL);
1698
+    fflush(stdout);
1699
+}
1700
+
1678 1701
 static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
1679 1702
                        AVFormatContext *fmt_ctx)
1680 1703
 {
... ...
@@ -1751,6 +1776,7 @@ static av_always_inline int process_frame(WriterContext *w,
1751 1751
                                           AVFrame *frame, AVPacket *pkt)
1752 1752
 {
1753 1753
     AVCodecContext *dec_ctx = fmt_ctx->streams[pkt->stream_index]->codec;
1754
+    AVSubtitle sub;
1754 1755
     int ret = 0, got_frame = 0;
1755 1756
 
1756 1757
     avcodec_get_frame_defaults(frame);
... ...
@@ -1763,6 +1789,10 @@ static av_always_inline int process_frame(WriterContext *w,
1763 1763
         case AVMEDIA_TYPE_AUDIO:
1764 1764
             ret = avcodec_decode_audio4(dec_ctx, frame, &got_frame, pkt);
1765 1765
             break;
1766
+
1767
+        case AVMEDIA_TYPE_SUBTITLE:
1768
+            ret = avcodec_decode_subtitle2(dec_ctx, &sub, &got_frame, pkt);
1769
+            break;
1766 1770
         }
1767 1771
     }
1768 1772
 
... ...
@@ -1772,9 +1802,15 @@ static av_always_inline int process_frame(WriterContext *w,
1772 1772
     pkt->data += ret;
1773 1773
     pkt->size -= ret;
1774 1774
     if (got_frame) {
1775
+        int is_sub = (dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE);
1775 1776
         nb_streams_frames[pkt->stream_index]++;
1776 1777
         if (do_show_frames)
1777
-            show_frame(w, frame, fmt_ctx->streams[pkt->stream_index], fmt_ctx);
1778
+            if (is_sub)
1779
+                show_subtitle(w, &sub, fmt_ctx->streams[pkt->stream_index], fmt_ctx);
1780
+            else
1781
+                show_frame(w, frame, fmt_ctx->streams[pkt->stream_index], fmt_ctx);
1782
+        if (is_sub)
1783
+            avsubtitle_free(&sub);
1778 1784
     }
1779 1785
     return got_frame;
1780 1786
 }