Always pass 0-sized packets to the decoder, instead of initiating drain
mode.

This fixes behavior with "legitimate" 0-sized packets that appear mid-
stream, and which are _not_ flush packets.

It leaves handling of 0-sized packets loosely defined - this constitutes
an API change, because the user now strictly has to pass NULL to
avcodec_send_packet() to initiate draining correctly.
---
 avconv.c             | 4 ++--
 doc/APIchanges       | 4 ++++
 libavcodec/avcodec.h | 9 +++++++--
 libavcodec/utils.c   | 2 +-
 4 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/avconv.c b/avconv.c
index 1351cfc..e8f6464 100644
--- a/avconv.c
+++ b/avconv.c
@@ -1118,7 +1118,7 @@ static void do_streamcopy(InputStream *ist, OutputStream 
*ost, const AVPacket *p
 // This does not quite work like avcodec_decode_audio4/avcodec_decode_video2.
 // There is the following difference: if you got a frame, you must call
 // it again with pkt=NULL. pkt==NULL is treated differently from pkt.size==0
-// (pkt==NULL means get more output, pkt.size==0 is a flush/drain packet)
+// (pkt==NULL means get more output, pkt.data==NULL is a flush/drain packet)
 static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, 
AVPacket *pkt)
 {
     int ret;
@@ -1126,7 +1126,7 @@ static int decode(AVCodecContext *avctx, AVFrame *frame, 
int *got_frame, AVPacke
     *got_frame = 0;
 
     if (pkt) {
-        ret = avcodec_send_packet(avctx, pkt);
+        ret = avcodec_send_packet(avctx, pkt->data ? pkt : NULL);
         // In particular, we don't expect AVERROR(EAGAIN), because we read all
         // decoded frames with avcodec_receive_frame() until done.
         if (ret < 0)
diff --git a/doc/APIchanges b/doc/APIchanges
index c3b81fa..6551522 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,10 @@ libavutil:     2015-08-28
 
 API changes, most recent first:
 
+2016-xx-xx - xxxxxxx - lavc 57.xx.0 - avcodec.h
+  Change the semantics of avcodec_send_packet() in cases AVPackets with
+  size=0 are passed to it.
+
 2016-xx-xx - xxxxxxx - lavu 55.10.0 - opt.h
   Add av_opt_copy().
 
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 26e6eb3..a10ceaa 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -4222,13 +4222,18 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, 
AVSubtitle *sub,
  *                  and if it contains multiple frames (e.g. some audio 
codecs),
  *                  will require you to call avcodec_receive_frame() multiple
  *                  times afterwards before you can send a new packet.
- *                  It can be NULL (or an AVPacket with data set to NULL and
- *                  size set to 0); in this case, it is considered a flush
+ *                  It can be NULL; in this case, it is considered a flush
  *                  packet, which signals the end of the stream. Sending the
  *                  first flush packet will return success. Subsequent ones are
  *                  unnecessary and will return AVERROR_EOF. If the decoder
  *                  still has frames buffered, it will return them after 
sending
  *                  a flush packet.
+ *                  Packets with size set to 0 have loosely defined behavior.
+ *                  Passing them to this function may or may not result in an
+ *                  eventual AVERROR_EOF, and (independently from this) may or
+ *                  may not be interpreted by the decoder as flush packet. You
+ *                  should avoid trying to send 0-sized packets for flushing;
+ *                  call the function with a NULL packet instead.
  *
  * @return 0 on success, otherwise negative error code:
  *      AVERROR(EAGAIN):   input is not accepted right now - the packet must be
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index d42885d..65f601f 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -1727,7 +1727,7 @@ int attribute_align_arg 
avcodec_send_packet(AVCodecContext *avctx, const AVPacke
     if (avctx->internal->draining)
         return AVERROR_EOF;
 
-    if (!avpkt || !avpkt->size) {
+    if (!avpkt) {
         avctx->internal->draining = 1;
         avpkt = NULL;
 
-- 
2.8.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to