[FFmpeg-devel] [PATCH 4/6] lavc: support multiple frames in a singe AVPacket in avcodec_decode_subtitle2

Marton Balint cus at passwd.hu
Sat Oct 5 19:34:56 CEST 2013


This feature is also known as CODEC_CAP_SUBFRAMES support. The patch also adds
CODEC_CAP_DELAY support to avcodec_decode_subtitle2.

For DVB teletext decoding, a single teletext packet can contain multiple
teletext pages. In order to support that, we extend the API the same way it is
used now for audio decoding.

Signed-off-by: Marton Balint <cus at passwd.hu>
---
 doc/APIchanges       |  4 ++++
 ffmpeg.c             |  2 +-
 libavcodec/avcodec.h | 13 +++++++++++++
 libavcodec/utils.c   | 11 +++++++++--
 libavcodec/version.h |  2 +-
 libavformat/utils.c  |  1 -
 6 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index dc43313..1706c97 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,6 +15,10 @@ libavutil:     2012-10-22
 
 API changes, most recent first:
 
+2013-10-xx - xxxxxxx - lavc 55.35.100 - avcodec.h
+  Add CODEC_CAP_DELAY and CODEC_CAP_SUBFRAMES support to
+  avcodec_decode_subtitle2.
+
 2013-10-03 - xxxxxxx - lavc 55.34.100 - avcodec.h
   Add av_codec_get_max_lowres()
 
diff --git a/ffmpeg.c b/ffmpeg.c
index d1c841f..47c94aa 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -1897,7 +1897,7 @@ static int output_packet(InputStream *ist, const AVPacket *pkt)
 
         // touch data and size only if not EOF
         if (pkt) {
-            if(ist->st->codec->codec_type != AVMEDIA_TYPE_AUDIO)
+            if(ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
                 ret = avpkt.size;
             avpkt.data += ret;
             avpkt.size -= ret;
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 2917a2f..5447a8e 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -3875,11 +3875,24 @@ int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
  * Return a negative value on error, otherwise return the number of bytes used.
  * If no subtitle could be decompressed, got_sub_ptr is zero.
  * Otherwise, the subtitle is stored in *sub.
+ *
+ * Some decoders may support multiple frames in a single AVPacket. Such
+ * decoders would then just decode the first frame. In this case,
+ * avcodec_decode_subtitle2 has to be called again with an AVPacket containing
+ * the remaining data in order to decode the second frame, etc...
+ * Even if no frames are returned, or a frame is returned but no data is
+ * consumed, the packet needs to be fed to the decoder with remaining data
+ * until it is completely consumed or an error occurs.
+ *
  * Note that CODEC_CAP_DR1 is not available for subtitle codecs. This is for
  * simplicity, because the performance difference is expect to be negligible
  * and reusing a get_buffer written for video codecs would probably perform badly
  * due to a potentially very different allocation pattern.
  *
+ * @note Codecs which have the CODEC_CAP_DELAY capability set have a delay
+ * between input and output, these need to be fed with avpkt->data=NULL,
+ * avpkt->size=0 at the end to return the remaining frames.
+ *
  * @param avctx the codec context
  * @param[out] sub The AVSubtitle in which the decoded subtitle will be stored, must be
                    freed with avsubtitle_free if *got_sub_ptr is set.
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 20de48e..ea30c39 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -2330,15 +2330,22 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
 {
     int i, ret = 0;
 
+    *got_sub_ptr = 0;
+
+    if (!avpkt->data && avpkt->size) {
+        av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n");
+        return AVERROR(EINVAL);
+    }
+    if (!avctx->codec)
+        return AVERROR(EINVAL);
     if (avctx->codec->type != AVMEDIA_TYPE_SUBTITLE) {
         av_log(avctx, AV_LOG_ERROR, "Invalid media type for subtitles\n");
         return AVERROR(EINVAL);
     }
 
-    *got_sub_ptr = 0;
     avcodec_get_subtitle_defaults(sub);
 
-    if (avpkt->size) {
+    if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size) {
         AVPacket pkt_recoded;
         AVPacket tmp = *avpkt;
         int did_split = av_packet_split_side_data(&tmp);
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 7f9682e..63a2d8f 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@
 #include "libavutil/avutil.h"
 
 #define LIBAVCODEC_VERSION_MAJOR 55
-#define LIBAVCODEC_VERSION_MINOR  34
+#define LIBAVCODEC_VERSION_MINOR  35
 #define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 61405d7..becac14 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -2512,7 +2512,6 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt, A
         case AVMEDIA_TYPE_SUBTITLE:
             ret = avcodec_decode_subtitle2(st->codec, &subtitle,
                                            &got_picture, &pkt);
-            ret = pkt.size;
             break;
         default:
             break;
-- 
1.8.1.4



More information about the ffmpeg-devel mailing list