[FFmpeg-devel] [PATCH] lavc/h264: warn on mixed non-IDR/IDR NAL units

2018-09-04 Thread joshdk
From: Josh de Kock 

No segfault on sample ticket 4408.
---
 libavcodec/h264dec.c | 23 ++-
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 8d115fa040..2ab52f57c0 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -601,7 +601,7 @@ static int decode_nal_units(H264Context *h, const uint8_t 
*buf, int buf_size)
 {
 AVCodecContext *const avctx = h->avctx;
 int nals_needed = 0; ///< number of NALs that need decoding before the 
next frame thread starts
-int idr_cleared=0;
+int slice_run = 0;
 int i, ret = 0;
 
 h->has_slice = 0;
@@ -656,19 +656,23 @@ static int decode_nal_units(H264Context *h, const uint8_t 
*buf, int buf_size)
 ret = -1;
 goto end;
 }
-if(!idr_cleared) {
-if (h->current_slice && (avctx->active_thread_type & 
FF_THREAD_SLICE)) {
-av_log(h, AV_LOG_ERROR, "invalid mixed IDR / non IDR 
frames cannot be decoded in slice multithreading mode\n");
-ret = AVERROR_INVALIDDATA;
-goto end;
-}
-idr(h); // FIXME ensure we don't lose some frames if there is 
reordering
+if (slice_run >= 0)
+slice_run++;
+if (slice_run < 0) {
+av_log(h, AV_LOG_WARNING, "encountered IDR slice after non-IDR 
slice before PPS (is PPS missing?)\n");
 }
-idr_cleared = 1;
+
+idr(h); // FIXME ensure we don't lose some frames if there is 
reordering
 h->has_recovery_point = 1;
 case H264_NAL_SLICE:
 h->has_slice = 1;
 
+if (slice_run <= 0)
+slice_run--;
+if (slice_run > 0) {
+av_log(h, AV_LOG_WARNING, "encountered non-IDR slice after IDR 
slice before PPS (is PPS missing?)\n");
+}
+
 if ((err = ff_h264_queue_decode_slice(h, nal))) {
 H264SliceContext *sl = h->slice_ctx + h->nb_slice_ctx_queued;
 sl->ref_count[0] = sl->ref_count[1] = 0;
@@ -732,6 +736,7 @@ static int decode_nal_units(H264Context *h, const uint8_t 
*buf, int buf_size)
 break;
 }
 case H264_NAL_PPS:
+slice_run = 0;
 if (avctx->hwaccel && avctx->hwaccel->decode_params) {
 ret = avctx->hwaccel->decode_params(avctx,
 nal->type,
-- 
2.17.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/2] lavc/h264dec: don't error out when receiving multiple IDR slices

2018-09-26 Thread joshdk
From: Josh de Kock 

This error isn't particularly helpful as checking for mixed IDR/non-IDR
NALUs would need to be done at a higher level to actually be accurate.
Removing the error allows an API user to send individual slice NALUs
(i.e. incomplete frames) so they can take advantage of slice
threading. The ticket which this error was added for (#4408) no
longer segfaults after removing this error (as the bug was likely
fixed more properly elsewhere).
---
 libavcodec/h264dec.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 7b4c5c76ea..00d922fbe9 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -657,11 +657,6 @@ static int decode_nal_units(H264Context *h, const uint8_t 
*buf, int buf_size)
 goto end;
 }
 if(!idr_cleared) {
-if (h->current_slice && (avctx->active_thread_type & 
FF_THREAD_SLICE)) {
-av_log(h, AV_LOG_ERROR, "invalid mixed IDR / non IDR 
frames cannot be decoded in slice multithreading mode\n");
-ret = AVERROR_INVALIDDATA;
-goto end;
-}
 idr(h); // FIXME ensure we don't lose some frames if there is 
reordering
 }
 idr_cleared = 1;
-- 
2.17.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/2] fate: add api-h264-slice test

2018-09-26 Thread joshdk
From: Josh de Kock 

This test ensures that you are able to send N number of slice NALUs in slice 
threaded mode to be decoded simultaneously
---
 tests/api/Makefile  |   1 +
 tests/api/api-h264-slice-test.c | 208 +
 tests/fate/api.mak  |   4 +
 tests/ref/fate/api-h264-slice   | 309 
 4 files changed, 522 insertions(+)
 create mode 100644 tests/api/api-h264-slice-test.c
 create mode 100644 tests/ref/fate/api-h264-slice

diff --git a/tests/api/Makefile b/tests/api/Makefile
index 759dd9d243..b5c4ccae23 100644
--- a/tests/api/Makefile
+++ b/tests/api/Makefile
@@ -1,5 +1,6 @@
 APITESTPROGS-$(call ENCDEC, FLAC, FLAC) += api-flac
 APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264
+APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice
 APITESTPROGS-yes += api-seek
 APITESTPROGS-yes += api-codec-param
 APITESTPROGS-$(call DEMDEC, H263, H263) += api-band
diff --git a/tests/api/api-h264-slice-test.c b/tests/api/api-h264-slice-test.c
new file mode 100644
index 00..c357291eee
--- /dev/null
+++ b/tests/api/api-h264-slice-test.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2001 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define MAX_SLICES 8
+
+// ./fate 2 ./crew_cif out.y4m
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+static int header = 0;
+static FILE *ofd;
+
+static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
+   AVPacket *pkt)
+{
+static long int frame_cnt = 0;
+int ret;
+
+ret = avcodec_send_packet(dec_ctx, pkt);
+if (ret < 0) {
+fprintf(stderr, "Error sending a packet for decoding: %s\n", 
av_err2str(ret));
+exit(1);
+}
+
+while (ret >= 0) {
+const AVPixFmtDescriptor *desc;
+char *sum;
+struct AVHashContext *hash;
+
+ret = avcodec_receive_frame(dec_ctx, frame);
+if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+return;
+} else if (ret < 0) {
+fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret));
+exit(1);
+}
+
+if (!header) {
+printf(
+"#format: frame checksums\n"
+"#version: 2\n"
+"#hash: MD5\n"
+"#tb 0: 1/30\n"
+"#media_type 0: video\n"
+"#codec_id 0: rawvideo\n"
+"#dimensions 0: 352x288\n"
+"#sar 0: 128/117\n"
+"#stream#, dts,pts, duration, size, hash\n");
+header = 1;
+}
+desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt);
+av_hash_alloc(&hash, "md5");
+av_hash_init(hash);
+sum = av_mallocz(av_hash_get_size(hash) * 2 + 1);
+
+for (int i = 0; i < frame->height; i++)
+av_hash_update(hash, &frame->data[0][i * frame->linesize[0]], 
frame->width);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[1][i * frame->linesize[1]], 
frame->width >> desc->log2_chroma_w);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[2][i * frame->linesize[2]], 
frame->width >> desc->log2_chroma_w);
+
+av_hash_final_hex(hash, sum, av_hash_get_size(hash) * 2 + 1);
+printf("0, %10"PRId64", %10"PRId64",1, %8d, %s\n",
+frame_cnt, frame_cnt,
+(frame->width * frame->height + 2 * (frame->height >> 
desc->log2_chroma_h) * (frame->width >> desc->log2_chroma_w)), sum); 
+frame_cnt += 1;
+av_free(hash);
+av_free(sum);
+}
+}
+
+int main(int argc, char **argv)
+{
+const AVCodec *codec;
+AVCodecContext *c = NULL;
+AVFrame *frame;
+unsigned int threads;
+AVPacket *pkt;
+int fd = 0;
+char nal[MAX_SLICES * UINT16_MAX + AV_

[FFmpeg-devel] [PATCH v2] fate: add api-h264-slice test

2018-09-27 Thread joshdk
From: Josh de Kock 

This test ensures that you are able to send N number of slice NALUs in slice 
threaded mode to be decoded simultaneously
---

 Tested 32bit with --arch=x86_32

 tests/api/Makefile  |   1 +
 tests/api/api-h264-slice-test.c | 212 ++
 tests/fate/api.mak  |   4 +
 tests/ref/fate/api-h264-slice   | 309 
 4 files changed, 526 insertions(+)
 create mode 100644 tests/api/api-h264-slice-test.c
 create mode 100644 tests/ref/fate/api-h264-slice

diff --git a/tests/api/Makefile b/tests/api/Makefile
index 759dd9d243..b5c4ccae23 100644
--- a/tests/api/Makefile
+++ b/tests/api/Makefile
@@ -1,5 +1,6 @@
 APITESTPROGS-$(call ENCDEC, FLAC, FLAC) += api-flac
 APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264
+APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice
 APITESTPROGS-yes += api-seek
 APITESTPROGS-yes += api-codec-param
 APITESTPROGS-$(call DEMDEC, H263, H263) += api-band
diff --git a/tests/api/api-h264-slice-test.c b/tests/api/api-h264-slice-test.c
new file mode 100644
index 00..347dd42ab4
--- /dev/null
+++ b/tests/api/api-h264-slice-test.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2001 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define MAX_SLICES 8
+
+// ./fate 2 ./crew_cif out.y4m
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+static int header = 0;
+static FILE *ofd;
+
+static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
+   AVPacket *pkt)
+{
+static long int frame_cnt = 0;
+int ret;
+
+ret = avcodec_send_packet(dec_ctx, pkt);
+if (ret < 0) {
+fprintf(stderr, "Error sending a packet for decoding: %s\n", 
av_err2str(ret));
+exit(1);
+}
+
+while (ret >= 0) {
+const AVPixFmtDescriptor *desc;
+char *sum;
+struct AVHashContext *hash;
+
+ret = avcodec_receive_frame(dec_ctx, frame);
+if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+return;
+} else if (ret < 0) {
+fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret));
+exit(1);
+}
+
+if (!header) {
+printf(
+"#format: frame checksums\n"
+"#version: 2\n"
+"#hash: MD5\n"
+"#tb 0: 1/30\n"
+"#media_type 0: video\n"
+"#codec_id 0: rawvideo\n"
+"#dimensions 0: 352x288\n"
+"#sar 0: 128/117\n"
+"#stream#, dts,pts, duration, size, hash\n");
+header = 1;
+}
+desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt);
+av_hash_alloc(&hash, "md5");
+av_hash_init(hash);
+sum = av_mallocz(av_hash_get_size(hash) * 2 + 1);
+
+for (int i = 0; i < frame->height; i++)
+av_hash_update(hash, &frame->data[0][i * frame->linesize[0]], 
frame->width);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[1][i * frame->linesize[1]], 
frame->width >> desc->log2_chroma_w);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[2][i * frame->linesize[2]], 
frame->width >> desc->log2_chroma_w);
+
+av_hash_final_hex(hash, sum, av_hash_get_size(hash) * 2 + 1);
+printf("0, %10"PRId64", %10"PRId64",1, %8d, %s\n",
+frame_cnt, frame_cnt,
+(frame->width * frame->height + 2 * (frame->height >> 
desc->log2_chroma_h) * (frame->width >> desc->log2_chroma_w)), sum); 
+frame_cnt += 1;
+av_free(hash);
+av_free(sum);
+}
+}
+
+int main(int argc, char **argv)
+{
+const AVCodec *codec;
+AVCodecContext *c = NULL;
+AVFrame *frame;
+unsigned int threads;
+AVPacket *pkt;
+int fd = 0;
+char nal[MAX_

[FFmpeg-devel] [PATCH v3] fate: add api-h264-slice test

2018-10-09 Thread joshdk
From: Josh de Kock 

This test ensures that you are able to send N number of slice NALUs in slice 
threaded mode to be decoded simultaneously
---

 Tested with `./configure --cc='cc -m32'` now, seems to be fine. Will send 
sample to Michael on IRC.

 tests/api/Makefile  |   1 +
 tests/api/api-h264-slice-test.c | 212 ++
 tests/fate/api.mak  |   4 +
 tests/ref/fate/api-h264-slice   | 309 
 4 files changed, 526 insertions(+)
 create mode 100644 tests/api/api-h264-slice-test.c
 create mode 100644 tests/ref/fate/api-h264-slice

diff --git a/tests/api/Makefile b/tests/api/Makefile
index 759dd9d243..b5c4ccae23 100644
--- a/tests/api/Makefile
+++ b/tests/api/Makefile
@@ -1,5 +1,6 @@
 APITESTPROGS-$(call ENCDEC, FLAC, FLAC) += api-flac
 APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264
+APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice
 APITESTPROGS-yes += api-seek
 APITESTPROGS-yes += api-codec-param
 APITESTPROGS-$(call DEMDEC, H263, H263) += api-band
diff --git a/tests/api/api-h264-slice-test.c b/tests/api/api-h264-slice-test.c
new file mode 100644
index 00..114561f3aa
--- /dev/null
+++ b/tests/api/api-h264-slice-test.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2001 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define MAX_SLICES 8
+
+// ./fate 2 ./crew_cif out.y4m
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+static int header = 0;
+static FILE *ofd;
+
+static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
+   AVPacket *pkt)
+{
+static uint64_t frame_cnt = 0;
+int ret;
+
+ret = avcodec_send_packet(dec_ctx, pkt);
+if (ret < 0) {
+fprintf(stderr, "Error sending a packet for decoding: %s\n", 
av_err2str(ret));
+exit(1);
+}
+
+while (ret >= 0) {
+const AVPixFmtDescriptor *desc;
+char *sum;
+struct AVHashContext *hash;
+
+ret = avcodec_receive_frame(dec_ctx, frame);
+if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+return;
+} else if (ret < 0) {
+fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret));
+exit(1);
+}
+
+if (!header) {
+printf(
+"#format: frame checksums\n"
+"#version: 2\n"
+"#hash: MD5\n"
+"#tb 0: 1/30\n"
+"#media_type 0: video\n"
+"#codec_id 0: rawvideo\n"
+"#dimensions 0: 352x288\n"
+"#sar 0: 128/117\n"
+"#stream#, dts,pts, duration, size, hash\n");
+header = 1;
+}
+desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt);
+av_hash_alloc(&hash, "md5");
+av_hash_init(hash);
+sum = av_mallocz(av_hash_get_size(hash) * 2 + 1);
+
+for (int i = 0; i < frame->height; i++)
+av_hash_update(hash, &frame->data[0][i * frame->linesize[0]], 
frame->width);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[1][i * frame->linesize[1]], 
frame->width >> desc->log2_chroma_w);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[2][i * frame->linesize[2]], 
frame->width >> desc->log2_chroma_w);
+
+av_hash_final_hex(hash, sum, av_hash_get_size(hash) * 2 + 1);
+printf("0, %10"PRId64", %10"PRId64",1, %8d, %s\n",
+frame_cnt, frame_cnt,
+(frame->width * frame->height + 2 * (frame->height >> 
desc->log2_chroma_h) * (frame->width >> desc->log2_chroma_w)), sum); 
+frame_cnt += 1;
+av_free(hash);
+av_free(sum);
+}
+}
+
+int main(int argc, char **argv)
+{
+const AVCodec *codec;
+AVCodecContext *c = NULL;
+AVFrame *frame;
+unsigned

[FFmpeg-devel] [PATCH 2/3] lavf/timecode: document SMPTE struct

2018-10-09 Thread joshdk
From: Devin Heitmueller 

There are a number of different binary representations in which
SMPTE timecodes can use.  Make clear that the specific representation
that ffmpeg refers to corresponds to the DV video spec, which is
SMPTE S314M:2005 for standard definition video and ST 370-2013 for
high definition video.
---
 libavutil/timecode.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libavutil/timecode.c b/libavutil/timecode.c
index 60077ba0c0..5b2bf85caa 100644
--- a/libavutil/timecode.c
+++ b/libavutil/timecode.c
@@ -117,6 +117,7 @@ static unsigned bcd2uint(uint8_t bcd)
 
 char *av_timecode_make_smpte_tc_string(char *buf, uint32_t tcsmpte, int 
prevent_df)
 {
+/* See SMPTE ST 314M-2005 Sec 4.4.2.2.1 "Time code pack (TC)" */
 unsigned hh   = bcd2uint(tcsmpte & 0x3f);// 6-bit hours
 unsigned mm   = bcd2uint(tcsmpte>>8  & 0x7f);// 7-bit minutes
 unsigned ss   = bcd2uint(tcsmpte>>16 & 0x7f);// 7-bit seconds
-- 
2.17.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 0/3] Timecode support

2018-10-09 Thread joshdk
This set requires Derek's patch to h264 which fixes #7083.
'h264_slice: Copy the value of x264_build before calling h264_slice_header_init 
during thread init'

Josh


___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 3/3] h264/pic_timing: support multiple timecodes

2018-10-09 Thread joshdk
From: Josh de Kock 

---
 libavcodec/h264_sei.c | 21 --
 libavcodec/h264_sei.h | 28 +--
 libavcodec/h264_slice.c   | 59 ++-
 libavfilter/vf_showinfo.c | 10 +++
 4 files changed, 75 insertions(+), 43 deletions(-)

diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index 275224eabe..d4eb9c0dab 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -84,8 +84,10 @@ static int decode_picture_timing(H264SEIPictureTiming *h, 
GetBitContext *gb,
 return AVERROR_INVALIDDATA;
 
 num_clock_ts = sei_num_clock_ts_table[h->pic_struct];
+h->timecode_cnt = 0;
 for (i = 0; i < num_clock_ts; i++) {
 if (get_bits(gb, 1)) {  /* 
clock_timestamp_flag */
+H264SEITimeCode *tc = &h->timecode[h->timecode_cnt++];
 unsigned int full_timestamp_flag;
 unsigned int counting_type, cnt_dropped_flag;
 h->ct_type |= 1 << get_bits(gb, 2);
@@ -95,20 +97,21 @@ static int decode_picture_timing(H264SEIPictureTiming *h, 
GetBitContext *gb,
 skip_bits(gb, 1);   /* discontinuity_flag 
*/
 cnt_dropped_flag = get_bits(gb, 1);  /* cnt_dropped_flag */
 if (cnt_dropped_flag && counting_type > 1 && counting_type < 7)
-h->tc_dropframe = 1;
-h->tc_frames = get_bits(gb, 8); /* n_frames */
+tc->dropframe = 1;
+tc->frame = get_bits(gb, 8); /* n_frames */
 if (full_timestamp_flag) {
-h->fulltc_received = 1;
-h->tc_seconds = get_bits(gb, 6); /* seconds_value 0..59 */
-h->tc_minutes = get_bits(gb, 6); /* minutes_value 0..59 */
-h->tc_hours = get_bits(gb, 5);   /* hours_value 0..23 */
+tc->full = 1;
+tc->seconds = get_bits(gb, 6); /* seconds_value 0..59 */
+tc->minutes = get_bits(gb, 6); /* minutes_value 0..59 */
+tc->hours = get_bits(gb, 5);   /* hours_value 0..23 */
 } else {
+tc->seconds = tc->minutes = tc->hours = tc->full = 0;
 if (get_bits(gb, 1)) { /* seconds_flag */
-h->tc_seconds = get_bits(gb, 6);
+tc->seconds = get_bits(gb, 6);
 if (get_bits(gb, 1)) { /* minutes_flag */
-h->tc_minutes = get_bits(gb, 6);
+tc->minutes = get_bits(gb, 6);
 if (get_bits(gb, 1))   /* hours_flag */
-h->tc_minutes = get_bits(gb, 5);
+tc->hours = get_bits(gb, 5);
 }
 }
 }
diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h
index 3b8806be0a..a75c3aa175 100644
--- a/libavcodec/h264_sei.h
+++ b/libavcodec/h264_sei.h
@@ -67,6 +67,17 @@ typedef enum {
 H264_SEI_FPA_TYPE_2D  = 6,
 } H264_SEI_FpaType;
 
+typedef struct H264SEITimeCode {
+/* When not continuously receiving full timecodes, we have to reference
+   the previous timecode received */
+int full;
+int frame;
+int seconds;
+int minutes;
+int hours;
+int dropframe;
+} H264SEITimeCode;
+
 typedef struct H264SEIPictureTiming {
 int present;
 H264_SEI_PicStructType pic_struct;
@@ -88,14 +99,15 @@ typedef struct H264SEIPictureTiming {
  */
 int cpb_removal_delay;
 
-/* When not continuously receiving full timecodes, we have to reference
-   the previous timecode received */
-int fulltc_received;
-int tc_frames;
-int tc_seconds;
-int tc_minutes;
-int tc_hours;
-int tc_dropframe;
+/**
+ * Maximum three timecodes in a pic_timing SEI.
+ */
+H264SEITimeCode timecode[3];
+
+/**
+ * Number of timecode in use
+ */
+int timecode_cnt;
 } H264SEIPictureTiming;
 
 typedef struct H264SEIAFD {
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 973f5761ef..aaf0006a32 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -1287,42 +1287,49 @@ static int h264_export_frame_props(H264Context *h)
 h->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
 }
 
-if (h->sei.picture_timing.fulltc_received) {
+if (h->sei.picture_timing.timecode_cnt > 0) {
 uint32_t tc = 0;
-uint32_t frames;
+uint32_t *tc_sd;
 
 AVFrameSideData *tcside = av_frame_new_side_data(cur->f,
  
AV_FRAME_DATA_S12M_TIMECODE,
- sizeof(uint32_t));
+ sizeof(uint32_t)*4);
 if (!tcside)

[FFmpeg-devel] [PATCH 1/3] lavc/h264: create AVFrame side data from H.264 timecodes

2018-10-09 Thread joshdk
From: Devin Heitmueller 

Create SMPTE ST 12-1 timecodes based on H.264 SEI picture timing
info.

For framerates > 30 FPS, the field flag is used in conjunction with
pairs of frames which contain the same frame timestamp in S12M.
Ensure the field is properly set per the spec.
---
 fftools/ffprobe.c   |  4 
 libavcodec/h264_sei.c   | 37 -
 libavcodec/h264_sei.h   |  9 +
 libavcodec/h264_slice.c | 38 ++
 libavutil/frame.c   |  1 +
 libavutil/frame.h   |  6 ++
 6 files changed, 78 insertions(+), 17 deletions(-)

diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 544786ec72..6cc3a4efc4 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -2199,6 +2199,10 @@ static void show_frame(WriterContext *w, AVFrame *frame, 
AVStream *stream,
 char tcbuf[AV_TIMECODE_STR_SIZE];
 av_timecode_make_mpeg_tc_string(tcbuf, *(int64_t *)(sd->data));
 print_str("timecode", tcbuf);
+} else if (sd->type == AV_FRAME_DATA_S12M_TIMECODE && sd->size >= 
4) {
+char tcbuf[AV_TIMECODE_STR_SIZE];
+av_timecode_make_smpte_tc_string(tcbuf, *(uint32_t 
*)(sd->data), 0);
+print_str("timecode", tcbuf);
 } else if (sd->type == AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
 AVMasteringDisplayMetadata *metadata = 
(AVMasteringDisplayMetadata *)sd->data;
 
diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index 43593d34d2..275224eabe 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -84,32 +84,35 @@ static int decode_picture_timing(H264SEIPictureTiming *h, 
GetBitContext *gb,
 return AVERROR_INVALIDDATA;
 
 num_clock_ts = sei_num_clock_ts_table[h->pic_struct];
-
 for (i = 0; i < num_clock_ts; i++) {
-if (get_bits(gb, 1)) {/* clock_timestamp_flag */
+if (get_bits(gb, 1)) {  /* 
clock_timestamp_flag */
 unsigned int full_timestamp_flag;
-
+unsigned int counting_type, cnt_dropped_flag;
 h->ct_type |= 1 << get_bits(gb, 2);
-skip_bits(gb, 1); /* nuit_field_based_flag */
-skip_bits(gb, 5); /* counting_type */
+skip_bits(gb, 1);   /* 
nuit_field_based_flag */
+counting_type = get_bits(gb, 5);/* counting_type */
 full_timestamp_flag = get_bits(gb, 1);
-skip_bits(gb, 1); /* discontinuity_flag */
-skip_bits(gb, 1); /* cnt_dropped_flag */
-skip_bits(gb, 8); /* n_frames */
+skip_bits(gb, 1);   /* discontinuity_flag 
*/
+cnt_dropped_flag = get_bits(gb, 1);  /* cnt_dropped_flag */
+if (cnt_dropped_flag && counting_type > 1 && counting_type < 7)
+h->tc_dropframe = 1;
+h->tc_frames = get_bits(gb, 8); /* n_frames */
 if (full_timestamp_flag) {
-skip_bits(gb, 6); /* seconds_value 0..59 */
-skip_bits(gb, 6); /* minutes_value 0..59 */
-skip_bits(gb, 5); /* hours_value 0..23 */
+h->fulltc_received = 1;
+h->tc_seconds = get_bits(gb, 6); /* seconds_value 0..59 */
+h->tc_minutes = get_bits(gb, 6); /* minutes_value 0..59 */
+h->tc_hours = get_bits(gb, 5);   /* hours_value 0..23 */
 } else {
-if (get_bits(gb, 1)) {/* seconds_flag */
-skip_bits(gb, 6); /* seconds_value range 0..59 
*/
-if (get_bits(gb, 1)) {/* minutes_flag */
-skip_bits(gb, 6); /* minutes_value 0..59 */
-if (get_bits(gb, 1))  /* hours_flag */
-skip_bits(gb, 5); /* hours_value 0..23 */
+if (get_bits(gb, 1)) { /* seconds_flag */
+h->tc_seconds = get_bits(gb, 6);
+if (get_bits(gb, 1)) { /* minutes_flag */
+h->tc_minutes = get_bits(gb, 6);
+if (get_bits(gb, 1))   /* hours_flag */
+h->tc_minutes = get_bits(gb, 5);
 }
 }
 }
+
 if (sps->time_offset_length > 0)
 skip_bits(gb,
   sps->time_offset_length); /* time_offset */
diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h
index 5b7c8ef9d8..3b8806be0a 100644
--- a/libavcodec/h264_sei.h
+++ b/libavcodec/h264_sei.h
@@ -87,6 +87,15 @@ typedef

[FFmpeg-devel] [PATCH] fate: add api-h264-slice test

2018-10-12 Thread joshdk
From: Josh de Kock 

This test ensures that you are able to send N number of slice NALUs in slice 
threaded mode to be decoded simultaneously
---
 tests/api/Makefile  |   1 +
 tests/api/api-h264-slice-test.c | 213 ++
 tests/fate/api.mak  |   4 +
 tests/ref/fate/api-h264-slice   | 309 
 4 files changed, 527 insertions(+)
 create mode 100644 tests/api/api-h264-slice-test.c
 create mode 100644 tests/ref/fate/api-h264-slice

diff --git a/tests/api/Makefile b/tests/api/Makefile
index 759dd9d243..b5c4ccae23 100644
--- a/tests/api/Makefile
+++ b/tests/api/Makefile
@@ -1,5 +1,6 @@
 APITESTPROGS-$(call ENCDEC, FLAC, FLAC) += api-flac
 APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264
+APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice
 APITESTPROGS-yes += api-seek
 APITESTPROGS-yes += api-codec-param
 APITESTPROGS-$(call DEMDEC, H263, H263) += api-band
diff --git a/tests/api/api-h264-slice-test.c b/tests/api/api-h264-slice-test.c
new file mode 100644
index 00..49c4153338
--- /dev/null
+++ b/tests/api/api-h264-slice-test.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2001 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define MAX_SLICES 8
+
+// ./fate 2 ./crew_cif out.y4m
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+static int header = 0;
+static FILE *ofd;
+
+static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
+   AVPacket *pkt)
+{
+static uint64_t frame_cnt = 0;
+int ret;
+
+ret = avcodec_send_packet(dec_ctx, pkt);
+if (ret < 0) {
+fprintf(stderr, "Error sending a packet for decoding: %s\n", 
av_err2str(ret));
+exit(1);
+}
+
+while (ret >= 0) {
+const AVPixFmtDescriptor *desc;
+char *sum;
+struct AVHashContext *hash;
+
+ret = avcodec_receive_frame(dec_ctx, frame);
+if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+return;
+} else if (ret < 0) {
+fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret));
+exit(1);
+}
+
+if (!header) {
+printf(
+"#format: frame checksums\n"
+"#version: 2\n"
+"#hash: MD5\n"
+"#tb 0: 1/30\n"
+"#media_type 0: video\n"
+"#codec_id 0: rawvideo\n"
+"#dimensions 0: 352x288\n"
+"#sar 0: 128/117\n"
+"#stream#, dts,pts, duration, size, hash\n");
+header = 1;
+}
+desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt);
+av_hash_alloc(&hash, "md5");
+av_hash_init(hash);
+sum = av_mallocz(av_hash_get_size(hash) * 2 + 1);
+
+for (int i = 0; i < frame->height; i++)
+av_hash_update(hash, &frame->data[0][i * frame->linesize[0]], 
frame->width);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[1][i * frame->linesize[1]], 
frame->width >> desc->log2_chroma_w);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[2][i * frame->linesize[2]], 
frame->width >> desc->log2_chroma_w);
+
+av_hash_final_hex(hash, sum, av_hash_get_size(hash) * 2 + 1);
+printf("0, %10"PRId64", %10"PRId64",1, %8d, %s\n",
+frame_cnt, frame_cnt,
+(frame->width * frame->height + 2 * (frame->height >> 
desc->log2_chroma_h) * (frame->width >> desc->log2_chroma_w)), sum); 
+frame_cnt += 1;
+av_free(hash);
+av_free(sum);
+}
+}
+
+int main(int argc, char **argv)
+{
+const AVCodec *codec;
+AVCodecContext *c = NULL;
+AVFrame *frame;
+unsigned int threads;
+AVPacket *pkt;
+FILE *fd;
+char nal[MAX_SLICES * UINT16_MAX + AV_INPUT_BUFFER

[FFmpeg-devel] [PATCH v2 1/4] lavc/h264: create AVFrame side data from H.264 timecodes

2018-10-12 Thread joshdk
From: Devin Heitmueller 

Create SMPTE ST 12-1 timecodes based on H.264 SEI picture timing
info.

For framerates > 30 FPS, the field flag is used in conjunction with
pairs of frames which contain the same frame timestamp in S12M.
Ensure the field is properly set per the spec.
---
 libavcodec/h264_sei.c   | 37 -
 libavcodec/h264_sei.h   |  9 +
 libavcodec/h264_slice.c | 38 ++
 libavutil/frame.c   |  1 +
 libavutil/frame.h   |  8 
 5 files changed, 76 insertions(+), 17 deletions(-)

diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index 43593d34d2..275224eabe 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -84,32 +84,35 @@ static int decode_picture_timing(H264SEIPictureTiming *h, 
GetBitContext *gb,
 return AVERROR_INVALIDDATA;
 
 num_clock_ts = sei_num_clock_ts_table[h->pic_struct];
-
 for (i = 0; i < num_clock_ts; i++) {
-if (get_bits(gb, 1)) {/* clock_timestamp_flag */
+if (get_bits(gb, 1)) {  /* 
clock_timestamp_flag */
 unsigned int full_timestamp_flag;
-
+unsigned int counting_type, cnt_dropped_flag;
 h->ct_type |= 1 << get_bits(gb, 2);
-skip_bits(gb, 1); /* nuit_field_based_flag */
-skip_bits(gb, 5); /* counting_type */
+skip_bits(gb, 1);   /* 
nuit_field_based_flag */
+counting_type = get_bits(gb, 5);/* counting_type */
 full_timestamp_flag = get_bits(gb, 1);
-skip_bits(gb, 1); /* discontinuity_flag */
-skip_bits(gb, 1); /* cnt_dropped_flag */
-skip_bits(gb, 8); /* n_frames */
+skip_bits(gb, 1);   /* discontinuity_flag 
*/
+cnt_dropped_flag = get_bits(gb, 1);  /* cnt_dropped_flag */
+if (cnt_dropped_flag && counting_type > 1 && counting_type < 7)
+h->tc_dropframe = 1;
+h->tc_frames = get_bits(gb, 8); /* n_frames */
 if (full_timestamp_flag) {
-skip_bits(gb, 6); /* seconds_value 0..59 */
-skip_bits(gb, 6); /* minutes_value 0..59 */
-skip_bits(gb, 5); /* hours_value 0..23 */
+h->fulltc_received = 1;
+h->tc_seconds = get_bits(gb, 6); /* seconds_value 0..59 */
+h->tc_minutes = get_bits(gb, 6); /* minutes_value 0..59 */
+h->tc_hours = get_bits(gb, 5);   /* hours_value 0..23 */
 } else {
-if (get_bits(gb, 1)) {/* seconds_flag */
-skip_bits(gb, 6); /* seconds_value range 0..59 
*/
-if (get_bits(gb, 1)) {/* minutes_flag */
-skip_bits(gb, 6); /* minutes_value 0..59 */
-if (get_bits(gb, 1))  /* hours_flag */
-skip_bits(gb, 5); /* hours_value 0..23 */
+if (get_bits(gb, 1)) { /* seconds_flag */
+h->tc_seconds = get_bits(gb, 6);
+if (get_bits(gb, 1)) { /* minutes_flag */
+h->tc_minutes = get_bits(gb, 6);
+if (get_bits(gb, 1))   /* hours_flag */
+h->tc_minutes = get_bits(gb, 5);
 }
 }
 }
+
 if (sps->time_offset_length > 0)
 skip_bits(gb,
   sps->time_offset_length); /* time_offset */
diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h
index 5b7c8ef9d8..3b8806be0a 100644
--- a/libavcodec/h264_sei.h
+++ b/libavcodec/h264_sei.h
@@ -87,6 +87,15 @@ typedef struct H264SEIPictureTiming {
  * cpb_removal_delay in picture timing SEI message, see H.264 C.1.2
  */
 int cpb_removal_delay;
+
+/* When not continuously receiving full timecodes, we have to reference
+   the previous timecode received */
+int fulltc_received;
+int tc_frames;
+int tc_seconds;
+int tc_minutes;
+int tc_hours;
+int tc_dropframe;
 } H264SEIPictureTiming;
 
 typedef struct H264SEIAFD {
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index d09cee4b13..f5415ba595 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -1287,6 +1287,44 @@ static int h264_export_frame_props(H264Context *h)
 h->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
 }
 
+if (h->sei.picture_timing.fulltc_received) {
+uint32_t tc = 0;
+uint32_t frames;
+
+AVFrameSideData *tcside 

[FFmpeg-devel] [PATCH v4 2/4] h264/pic_timing: support multiple timecodes

2018-10-12 Thread joshdk
From: Josh de Kock 

---
 There are no cosmetic changes which are not functional here.

 libavcodec/h264_sei.c   | 21 ---
 libavcodec/h264_sei.h   | 28 +--
 libavcodec/h264_slice.c | 59 +++--
 3 files changed, 65 insertions(+), 43 deletions(-)

diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index 275224eabe..d4eb9c0dab 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -84,8 +84,10 @@ static int decode_picture_timing(H264SEIPictureTiming *h, 
GetBitContext *gb,
 return AVERROR_INVALIDDATA;
 
 num_clock_ts = sei_num_clock_ts_table[h->pic_struct];
+h->timecode_cnt = 0;
 for (i = 0; i < num_clock_ts; i++) {
 if (get_bits(gb, 1)) {  /* 
clock_timestamp_flag */
+H264SEITimeCode *tc = &h->timecode[h->timecode_cnt++];
 unsigned int full_timestamp_flag;
 unsigned int counting_type, cnt_dropped_flag;
 h->ct_type |= 1 << get_bits(gb, 2);
@@ -95,20 +97,21 @@ static int decode_picture_timing(H264SEIPictureTiming *h, 
GetBitContext *gb,
 skip_bits(gb, 1);   /* discontinuity_flag 
*/
 cnt_dropped_flag = get_bits(gb, 1);  /* cnt_dropped_flag */
 if (cnt_dropped_flag && counting_type > 1 && counting_type < 7)
-h->tc_dropframe = 1;
-h->tc_frames = get_bits(gb, 8); /* n_frames */
+tc->dropframe = 1;
+tc->frame = get_bits(gb, 8); /* n_frames */
 if (full_timestamp_flag) {
-h->fulltc_received = 1;
-h->tc_seconds = get_bits(gb, 6); /* seconds_value 0..59 */
-h->tc_minutes = get_bits(gb, 6); /* minutes_value 0..59 */
-h->tc_hours = get_bits(gb, 5);   /* hours_value 0..23 */
+tc->full = 1;
+tc->seconds = get_bits(gb, 6); /* seconds_value 0..59 */
+tc->minutes = get_bits(gb, 6); /* minutes_value 0..59 */
+tc->hours = get_bits(gb, 5);   /* hours_value 0..23 */
 } else {
+tc->seconds = tc->minutes = tc->hours = tc->full = 0;
 if (get_bits(gb, 1)) { /* seconds_flag */
-h->tc_seconds = get_bits(gb, 6);
+tc->seconds = get_bits(gb, 6);
 if (get_bits(gb, 1)) { /* minutes_flag */
-h->tc_minutes = get_bits(gb, 6);
+tc->minutes = get_bits(gb, 6);
 if (get_bits(gb, 1))   /* hours_flag */
-h->tc_minutes = get_bits(gb, 5);
+tc->hours = get_bits(gb, 5);
 }
 }
 }
diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h
index 3b8806be0a..a75c3aa175 100644
--- a/libavcodec/h264_sei.h
+++ b/libavcodec/h264_sei.h
@@ -67,6 +67,17 @@ typedef enum {
 H264_SEI_FPA_TYPE_2D  = 6,
 } H264_SEI_FpaType;
 
+typedef struct H264SEITimeCode {
+/* When not continuously receiving full timecodes, we have to reference
+   the previous timecode received */
+int full;
+int frame;
+int seconds;
+int minutes;
+int hours;
+int dropframe;
+} H264SEITimeCode;
+
 typedef struct H264SEIPictureTiming {
 int present;
 H264_SEI_PicStructType pic_struct;
@@ -88,14 +99,15 @@ typedef struct H264SEIPictureTiming {
  */
 int cpb_removal_delay;
 
-/* When not continuously receiving full timecodes, we have to reference
-   the previous timecode received */
-int fulltc_received;
-int tc_frames;
-int tc_seconds;
-int tc_minutes;
-int tc_hours;
-int tc_dropframe;
+/**
+ * Maximum three timecodes in a pic_timing SEI.
+ */
+H264SEITimeCode timecode[3];
+
+/**
+ * Number of timecode in use
+ */
+int timecode_cnt;
 } H264SEIPictureTiming;
 
 typedef struct H264SEIAFD {
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index f5415ba595..2e158745a0 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -1287,42 +1287,49 @@ static int h264_export_frame_props(H264Context *h)
 h->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
 }
 
-if (h->sei.picture_timing.fulltc_received) {
+if (h->sei.picture_timing.timecode_cnt > 0) {
 uint32_t tc = 0;
-uint32_t frames;
+uint32_t *tc_sd;
 
 AVFrameSideData *tcside = av_frame_new_side_data(cur->f,
  
AV_FRAME_DATA_S12M_TIMECODE,
- sizeof(uint32_t));
+ sizeof(uint32_t)*4);
  

[FFmpeg-devel] [PATCH 3/4] lavfi/vf_showinfo: support displaying S12M timecode sidedata

2018-10-12 Thread joshdk
From: Josh de Kock 

---
 libavfilter/vf_showinfo.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c
index d1d1415c0b..689b5399db 100644
--- a/libavfilter/vf_showinfo.c
+++ b/libavfilter/vf_showinfo.c
@@ -32,6 +32,7 @@
 #include "libavutil/spherical.h"
 #include "libavutil/stereo3d.h"
 #include "libavutil/timestamp.h"
+#include "libavutil/timecode.h"
 
 #include "avfilter.h"
 #include "internal.h"
@@ -174,6 +175,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame 
*frame)
 case AV_FRAME_DATA_STEREO3D:
 dump_stereo3d(ctx, sd);
 break;
+case AV_FRAME_DATA_S12M_TIMECODE: {
+uint32_t *tc = (uint32_t*)sd->data;
+for (int j = 1; j < tc[0]; j++) {
+char tcbuf[AV_TIMECODE_STR_SIZE];
+av_timecode_make_smpte_tc_string(tcbuf, tc[j], 0);
+av_log(ctx, AV_LOG_INFO, "timecode - %s%s", tcbuf, j != tc[0] 
- 1 ? ", " : "");
+}
+break;
+}
 case AV_FRAME_DATA_DISPLAYMATRIX:
 av_log(ctx, AV_LOG_INFO, "displaymatrix: rotation of %.2f degrees",
av_display_rotation_get((int32_t *)sd->data));
-- 
2.17.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 4/4] fate: add h264 timecode test

2018-10-12 Thread joshdk
From: Josh de Kock 

---
 tests/fate/h264.mak  |   2 +
 tests/ref/fate/h264-timecode | 305 +++
 2 files changed, 307 insertions(+)
 create mode 100644 tests/ref/fate/h264-timecode

diff --git a/tests/fate/h264.mak b/tests/fate/h264.mak
index 1839b9b44e..f14b46c6e0 100644
--- a/tests/fate/h264.mak
+++ b/tests/fate/h264.mak
@@ -196,6 +196,7 @@ FATE_H264  := $(FATE_H264:%=fate-h264-conformance-%)
\
   fate-h264-3386\
   fate-h264-missing-frame   \
   fate-h264-ref-pic-mod-overflow\
+  fate-h264-timecode
 
 FATE_H264-$(call DEMDEC, H264, H264) += $(FATE_H264)
 FATE_H264-$(call DEMDEC,  MOV, H264) += fate-h264-crop-to-container
@@ -440,6 +441,7 @@ fate-h264-twofields-packet:   CMD = 
framecrc -i $(TARGET_SAM
 fate-h264-unescaped-extradata:CMD = framecrc -i 
$(TARGET_SAMPLES)/h264/unescaped_extradata.mp4 -an -frames 10
 fate-h264-3386:   CMD = framecrc -i 
$(TARGET_SAMPLES)/h264/bbc2.sample.h264
 fate-h264-missing-frame:  CMD = framecrc -i 
$(TARGET_SAMPLES)/h264/nondeterministic_cut.h264
+fate-h264-timecode:   CMD = framecrc -i 
$(TARGET_SAMPLES)/h264/crew_cif_timecode-2.h264
 
 fate-h264-reinit-%:   CMD = framecrc -i 
$(TARGET_SAMPLES)/h264/$(@:fate-h264-%=%).h264 -vf 
format=yuv444p10le,scale=w=352:h=288
 
diff --git a/tests/ref/fate/h264-timecode b/tests/ref/fate/h264-timecode
new file mode 100644
index 00..b78f700c6d
--- /dev/null
+++ b/tests/ref/fate/h264-timecode
@@ -0,0 +1,305 @@
+#tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 128/117
+0,  0,  0,1,   152064, 0x70684c80
+0,  1,  1,1,   152064, 0xb5c8b300
+0,  2,  2,1,   152064, 0x5777ac60
+0,  3,  3,1,   152064, 0xb27646a5
+0,  4,  4,1,   152064, 0x20bd98ec
+0,  5,  5,1,   152064, 0xcf5ac1b0
+0,  6,  6,1,   152064, 0x85a42952
+0,  7,  7,1,   152064, 0xc25aa530
+0,  8,  8,1,   152064, 0x97b14be9
+0,  9,  9,1,   152064, 0xf67ec91a
+0, 10, 10,1,   152064, 0x3890d6a3
+0, 11, 11,1,   152064, 0xc52c8467
+0, 12, 12,1,   152064, 0x30a7af36
+0, 13, 13,1,   152064, 0x27528a98
+0, 14, 14,1,   152064, 0x245c08c5
+0, 15, 15,1,   152064, 0x7e0220f3
+0, 16, 16,1,   152064, 0x4b254c89
+0, 17, 17,1,   152064, 0x1586e3e5
+0, 18, 18,1,   152064, 0x594dfc58
+0, 19, 19,1,   152064, 0x85ba9c8e
+0, 20, 20,1,   152064, 0x1e235100
+0, 21, 21,1,   152064, 0xa02c6a72
+0, 22, 22,1,   152064, 0xd1166fb6
+0, 23, 23,1,   152064, 0xcc9b1546
+0, 24, 24,1,   152064, 0x55e35a35
+0, 25, 25,1,   152064, 0xea63e2ae
+0, 26, 26,1,   152064, 0x936a1802
+0, 27, 27,1,   152064, 0x354a749c
+0, 28, 28,1,   152064, 0x5cd0f246
+0, 29, 29,1,   152064, 0x0376e69b
+0, 30, 30,1,   152064, 0x5af5fb61
+0, 31, 31,1,   152064, 0x9a053ab8
+0, 32, 32,1,   152064, 0x57cbbfcc
+0, 33, 33,1,   152064, 0x81f19e93
+0, 34, 34,1,   152064, 0x0812953d
+0, 35, 35,1,   152064, 0x0ae2a166
+0, 36, 36,1,   152064, 0x193125b8
+0, 37, 37,1,   152064, 0xab7eca7b
+0, 38, 38,1,   152064, 0x91ff1870
+0, 39, 39,1,   152064, 0x8f522dde
+0, 40, 40,1,   152064, 0x98faab46
+0, 41, 41,1,   152064, 0xa2119231
+0, 42, 42,1,   152064, 0xfe591321
+0, 43, 43,1,   152064, 0x6c8a1bf5
+0, 44, 44,1,   152064, 0x857c925c
+0, 45, 45,1,   152064, 0xe81a77f2
+0, 46, 46,1,   152064, 0x08234e83
+0, 47, 47,1,   152064, 0x76cb39f6
+0, 48, 48,1,   152064, 0x26168d25
+0, 49, 49,1,   152064, 0x4dd3b273
+0, 50, 50,1,   152064, 0xd6e8398e
+0, 51, 51,1,   152064, 0x55986a57
+0, 52, 52,1,   152064, 0x9c276

[FFmpeg-devel] [PATCH v3] fate: add api-h264-slice test

2018-10-12 Thread joshdk
From: Josh de Kock 

This test ensures that you are able to send N number of slice NALUs in slice 
threaded mode to be decoded simultaneously
---

 Ignore the previous patch, had some dead code in it. This now
 works in MinGW as well.

 tests/api/Makefile  |   1 +
 tests/api/api-h264-slice-test.c | 207 +
 tests/fate/api.mak  |   4 +
 tests/ref/fate/api-h264-slice   | 309 
 4 files changed, 521 insertions(+)
 create mode 100644 tests/api/api-h264-slice-test.c
 create mode 100644 tests/ref/fate/api-h264-slice

diff --git a/tests/api/Makefile b/tests/api/Makefile
index 759dd9d243..b5c4ccae23 100644
--- a/tests/api/Makefile
+++ b/tests/api/Makefile
@@ -1,5 +1,6 @@
 APITESTPROGS-$(call ENCDEC, FLAC, FLAC) += api-flac
 APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264
+APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice
 APITESTPROGS-yes += api-seek
 APITESTPROGS-yes += api-codec-param
 APITESTPROGS-$(call DEMDEC, H263, H263) += api-band
diff --git a/tests/api/api-h264-slice-test.c b/tests/api/api-h264-slice-test.c
new file mode 100644
index 00..aefcdc3928
--- /dev/null
+++ b/tests/api/api-h264-slice-test.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2001 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define MAX_SLICES 8
+
+// ./fate 2 ./crew_cif out.y4m
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+static int header = 0;
+
+static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
+   AVPacket *pkt)
+{
+static uint64_t frame_cnt = 0;
+int ret;
+
+ret = avcodec_send_packet(dec_ctx, pkt);
+if (ret < 0) {
+fprintf(stderr, "Error sending a packet for decoding: %s\n", 
av_err2str(ret));
+exit(1);
+}
+
+while (ret >= 0) {
+const AVPixFmtDescriptor *desc;
+char *sum;
+struct AVHashContext *hash;
+
+ret = avcodec_receive_frame(dec_ctx, frame);
+if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+return;
+} else if (ret < 0) {
+fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret));
+exit(1);
+}
+
+if (!header) {
+printf(
+"#format: frame checksums\n"
+"#version: 2\n"
+"#hash: MD5\n"
+"#tb 0: 1/30\n"
+"#media_type 0: video\n"
+"#codec_id 0: rawvideo\n"
+"#dimensions 0: 352x288\n"
+"#sar 0: 128/117\n"
+"#stream#, dts,pts, duration, size, hash\n");
+header = 1;
+}
+desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt);
+av_hash_alloc(&hash, "md5");
+av_hash_init(hash);
+sum = av_mallocz(av_hash_get_size(hash) * 2 + 1);
+
+for (int i = 0; i < frame->height; i++)
+av_hash_update(hash, &frame->data[0][i * frame->linesize[0]], 
frame->width);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[1][i * frame->linesize[1]], 
frame->width >> desc->log2_chroma_w);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[2][i * frame->linesize[2]], 
frame->width >> desc->log2_chroma_w);
+
+av_hash_final_hex(hash, sum, av_hash_get_size(hash) * 2 + 1);
+printf("0, %10"PRId64", %10"PRId64",1, %8d, %s\n",
+frame_cnt, frame_cnt,
+(frame->width * frame->height + 2 * (frame->height >> 
desc->log2_chroma_h) * (frame->width >> desc->log2_chroma_w)), sum); 
+frame_cnt += 1;
+av_free(hash);
+av_free(sum);
+}
+}
+
+int main(int argc, char **argv)
+{
+const AVCodec *codec;
+AVCodecContext *c = NULL;
+AVFrame *frame;
+unsigned int threads;
+AVPacket *pkt;

[FFmpeg-devel] [PATCH v4] fate: add api-h264-slice test

2018-10-15 Thread joshdk
From: Josh de Kock 

This test ensures that you are able to send N number of slice NALUs in slice 
threaded mode to be decoded simultaneously
---
 Tested on Linux 32/64, MinGW + WINE 32/64.

 tests/api/Makefile  |   1 +
 tests/api/api-h264-slice-test.c | 216 ++
 tests/fate/api.mak  |   4 +
 tests/ref/fate/api-h264-slice   | 309 
 4 files changed, 530 insertions(+)
 create mode 100644 tests/api/api-h264-slice-test.c
 create mode 100644 tests/ref/fate/api-h264-slice

diff --git a/tests/api/Makefile b/tests/api/Makefile
index 759dd9d243..b5c4ccae23 100644
--- a/tests/api/Makefile
+++ b/tests/api/Makefile
@@ -1,5 +1,6 @@
 APITESTPROGS-$(call ENCDEC, FLAC, FLAC) += api-flac
 APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264
+APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice
 APITESTPROGS-yes += api-seek
 APITESTPROGS-yes += api-codec-param
 APITESTPROGS-$(call DEMDEC, H263, H263) += api-band
diff --git a/tests/api/api-h264-slice-test.c b/tests/api/api-h264-slice-test.c
new file mode 100644
index 00..2021996d78
--- /dev/null
+++ b/tests/api/api-h264-slice-test.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2001 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define MAX_SLICES 8
+
+// ./fate 2 ./crew_cif out.y4m
+
+#include "config.h"
+
+#include 
+#include 
+#include 
+#include 
+
+#if HAVE_UNISTD_H
+#include 
+#endif
+#if HAVE_IO_H
+#include 
+#endif
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+static int header = 0;
+
+static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
+   AVPacket *pkt)
+{
+static uint64_t frame_cnt = 0;
+int ret;
+
+ret = avcodec_send_packet(dec_ctx, pkt);
+if (ret < 0) {
+fprintf(stderr, "Error sending a packet for decoding: %s\n", 
av_err2str(ret));
+exit(1);
+}
+
+while (ret >= 0) {
+const AVPixFmtDescriptor *desc;
+char *sum;
+struct AVHashContext *hash;
+
+ret = avcodec_receive_frame(dec_ctx, frame);
+if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+return;
+} else if (ret < 0) {
+fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret));
+exit(1);
+}
+
+if (!header) {
+printf(
+"#format: frame checksums\n"
+"#version: 2\n"
+"#hash: MD5\n"
+"#tb 0: 1/30\n"
+"#media_type 0: video\n"
+"#codec_id 0: rawvideo\n"
+"#dimensions 0: 352x288\n"
+"#sar 0: 128/117\n"
+"#stream#, dts,pts, duration, size, hash\n");
+header = 1;
+}
+desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt);
+av_hash_alloc(&hash, "md5");
+av_hash_init(hash);
+sum = av_mallocz(av_hash_get_size(hash) * 2 + 1);
+
+for (int i = 0; i < frame->height; i++)
+av_hash_update(hash, &frame->data[0][i * frame->linesize[0]], 
frame->width);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[1][i * frame->linesize[1]], 
frame->width >> desc->log2_chroma_w);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[2][i * frame->linesize[2]], 
frame->width >> desc->log2_chroma_w);
+
+av_hash_final_hex(hash, sum, av_hash_get_size(hash) * 2 + 1);
+printf("0, %10"PRId64", %10"PRId64",1, %8d, %s\n",
+frame_cnt, frame_cnt,
+(frame->width * frame->height + 2 * (frame->height >> 
desc->log2_chroma_h) * (frame->width >> desc->log2_chroma_w)), sum); 
+frame_cnt += 1;
+av_free(hash);
+av_free(sum);
+}
+}
+
+int main(int argc, char **argv)
+{
+const AVCodec *codec;
+AVCodecContext *c = NULL;
+AVFrame *frame;
+un

[FFmpeg-devel] [PATCH v5] fate: add api-h264-slice test

2018-10-23 Thread joshdk
From: Josh de Kock 

This test ensures that you are able to send N number of slice NALUs in slice 
threaded mode to be decoded simultaneously
---
 Prints a warning to the user when threading is not enabled, slice NALUs
 should still be checked for proper decoding irregardless of whether threads
 are enabled.

 Hopefully this is the last iteration, sorry this took so long. I'll now
 have a list of 'gotchas' for future test writing though :)

 tests/api/Makefile  |   1 +
 tests/api/api-h264-slice-test.c | 220 +++
 tests/fate/api.mak  |   4 +
 tests/ref/fate/api-h264-slice   | 309 
 4 files changed, 534 insertions(+)
 create mode 100644 tests/api/api-h264-slice-test.c
 create mode 100644 tests/ref/fate/api-h264-slice

diff --git a/tests/api/Makefile b/tests/api/Makefile
index 759dd9d243..b5c4ccae23 100644
--- a/tests/api/Makefile
+++ b/tests/api/Makefile
@@ -1,5 +1,6 @@
 APITESTPROGS-$(call ENCDEC, FLAC, FLAC) += api-flac
 APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264
+APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice
 APITESTPROGS-yes += api-seek
 APITESTPROGS-yes += api-codec-param
 APITESTPROGS-$(call DEMDEC, H263, H263) += api-band
diff --git a/tests/api/api-h264-slice-test.c b/tests/api/api-h264-slice-test.c
new file mode 100644
index 00..c87ceff109
--- /dev/null
+++ b/tests/api/api-h264-slice-test.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2001 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define MAX_SLICES 8
+
+// ./fate 2 ./crew_cif out.y4m
+
+#include "config.h"
+
+#include 
+#include 
+#include 
+#include 
+
+#if HAVE_UNISTD_H
+#include 
+#endif
+#if HAVE_IO_H
+#include 
+#endif
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+static int header = 0;
+
+static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
+   AVPacket *pkt)
+{
+static uint64_t frame_cnt = 0;
+int ret;
+
+ret = avcodec_send_packet(dec_ctx, pkt);
+if (ret < 0) {
+fprintf(stderr, "Error sending a packet for decoding: %s\n", 
av_err2str(ret));
+exit(1);
+}
+
+while (ret >= 0) {
+const AVPixFmtDescriptor *desc;
+char *sum;
+struct AVHashContext *hash;
+
+ret = avcodec_receive_frame(dec_ctx, frame);
+if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+return;
+} else if (ret < 0) {
+fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret));
+exit(1);
+}
+
+if (!header) {
+printf(
+"#format: frame checksums\n"
+"#version: 2\n"
+"#hash: MD5\n"
+"#tb 0: 1/30\n"
+"#media_type 0: video\n"
+"#codec_id 0: rawvideo\n"
+"#dimensions 0: 352x288\n"
+"#sar 0: 128/117\n"
+"#stream#, dts,pts, duration, size, hash\n");
+header = 1;
+}
+desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt);
+av_hash_alloc(&hash, "md5");
+av_hash_init(hash);
+sum = av_mallocz(av_hash_get_size(hash) * 2 + 1);
+
+for (int i = 0; i < frame->height; i++)
+av_hash_update(hash, &frame->data[0][i * frame->linesize[0]], 
frame->width);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[1][i * frame->linesize[1]], 
frame->width >> desc->log2_chroma_w);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[2][i * frame->linesize[2]], 
frame->width >> desc->log2_chroma_w);
+
+av_hash_final_hex(hash, sum, av_hash_get_size(hash) * 2 + 1);
+printf("0, %10"PRId64", %10"PRId64",1, %8d, %s\n",
+frame_cnt, frame_cnt,
+(frame->width * frame->height + 2 * (frame->height >> 
desc->log2_chroma_h) 

[FFmpeg-devel] [PATCH vFINAL] fate: add api-h264-slice test

2018-10-24 Thread joshdk
From: Josh de Kock 

This test ensures that you are able to send N number of slice NALUs in slice 
threaded mode to be decoded simultaneously
---
 Actually send fix.

 tests/api/Makefile  |   1 +
 tests/api/api-h264-slice-test.c | 221 +++
 tests/fate/api.mak  |   4 +
 tests/ref/fate/api-h264-slice   | 309 
 4 files changed, 535 insertions(+)
 create mode 100644 tests/api/api-h264-slice-test.c
 create mode 100644 tests/ref/fate/api-h264-slice

diff --git a/tests/api/Makefile b/tests/api/Makefile
index 759dd9d243..b5c4ccae23 100644
--- a/tests/api/Makefile
+++ b/tests/api/Makefile
@@ -1,5 +1,6 @@
 APITESTPROGS-$(call ENCDEC, FLAC, FLAC) += api-flac
 APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264
+APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice
 APITESTPROGS-yes += api-seek
 APITESTPROGS-yes += api-codec-param
 APITESTPROGS-$(call DEMDEC, H263, H263) += api-band
diff --git a/tests/api/api-h264-slice-test.c b/tests/api/api-h264-slice-test.c
new file mode 100644
index 00..961bdfbaf3
--- /dev/null
+++ b/tests/api/api-h264-slice-test.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2001 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define MAX_SLICES 8
+
+// ./fate 2 ./crew_cif out.y4m
+
+#include "config.h"
+
+#include 
+#include 
+#include 
+#include 
+
+#if HAVE_UNISTD_H
+#include 
+#endif
+#if HAVE_IO_H
+#include 
+#endif
+#include 
+#include 
+#include 
+
+#include "libavformat/network.h"
+#include "libavcodec/avcodec.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/hash.h"
+
+static int header = 0;
+
+static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
+   AVPacket *pkt)
+{
+static uint64_t frame_cnt = 0;
+int ret;
+
+ret = avcodec_send_packet(dec_ctx, pkt);
+if (ret < 0) {
+fprintf(stderr, "Error sending a packet for decoding: %s\n", 
av_err2str(ret));
+exit(1);
+}
+
+while (ret >= 0) {
+const AVPixFmtDescriptor *desc;
+char *sum;
+struct AVHashContext *hash;
+
+ret = avcodec_receive_frame(dec_ctx, frame);
+if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+return;
+} else if (ret < 0) {
+fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret));
+exit(1);
+}
+
+if (!header) {
+printf(
+"#format: frame checksums\n"
+"#version: 2\n"
+"#hash: MD5\n"
+"#tb 0: 1/30\n"
+"#media_type 0: video\n"
+"#codec_id 0: rawvideo\n"
+"#dimensions 0: 352x288\n"
+"#sar 0: 128/117\n"
+"#stream#, dts,pts, duration, size, hash\n");
+header = 1;
+}
+desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt);
+av_hash_alloc(&hash, "md5");
+av_hash_init(hash);
+sum = av_mallocz(av_hash_get_size(hash) * 2 + 1);
+
+for (int i = 0; i < frame->height; i++)
+av_hash_update(hash, &frame->data[0][i * frame->linesize[0]], 
frame->width);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[1][i * frame->linesize[1]], 
frame->width >> desc->log2_chroma_w);
+for (int i = 0; i < frame->height >> desc->log2_chroma_h; i++)
+av_hash_update(hash, &frame->data[2][i * frame->linesize[2]], 
frame->width >> desc->log2_chroma_w);
+
+av_hash_final_hex(hash, sum, av_hash_get_size(hash) * 2 + 1);
+printf("0, %10"PRId64", %10"PRId64",1, %8d, %s\n",
+frame_cnt, frame_cnt,
+(frame->width * frame->height + 2 * (frame->height >> 
desc->log2_chroma_h) * (frame->width >> desc->log2_chroma_w)), sum); 
+frame_cnt += 1;
+av_free(hash);
+av_free(sum);
+}
+}
+
+int main(int argc, char **argv)
+{
+const AVC

[FFmpeg-devel] [PATCH] fate/api-h264-slice-test: use cleaner error handling

2018-10-29 Thread joshdk
From: Josh de Kock 

---
 tests/api/api-h264-slice-test.c | 74 +++--
 1 file changed, 43 insertions(+), 31 deletions(-)

diff --git a/tests/api/api-h264-slice-test.c b/tests/api/api-h264-slice-test.c
index 57e7dc79c3..08d5d57941 100644
--- a/tests/api/api-h264-slice-test.c
+++ b/tests/api/api-h264-slice-test.c
@@ -48,7 +48,7 @@
 
 static int header = 0;
 
-static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
+static int decode(AVCodecContext *dec_ctx, AVFrame *frame,
AVPacket *pkt)
 {
 static uint64_t frame_cnt = 0;
@@ -57,20 +57,20 @@ static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
 ret = avcodec_send_packet(dec_ctx, pkt);
 if (ret < 0) {
 fprintf(stderr, "Error sending a packet for decoding: %s\n", 
av_err2str(ret));
-exit(1);
+return ret;
 }
 
 while (ret >= 0) {
 const AVPixFmtDescriptor *desc;
-char *sum;
+char sum[AV_HASH_MAX_SIZE * 2 + 1];
 struct AVHashContext *hash;
 
 ret = avcodec_receive_frame(dec_ctx, frame);
 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
-return;
+return 0;
 } else if (ret < 0) {
 fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret));
-exit(1);
+return ret;
 }
 
 if (!header) {
@@ -87,9 +87,10 @@ static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
 header = 1;
 }
 desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt);
-av_hash_alloc(&hash, "md5");
+if ((ret = av_hash_alloc(&hash, "md5")) < 0) {
+return ret;
+}
 av_hash_init(hash);
-sum = av_mallocz(av_hash_get_size(hash) * 2 + 1);
 
 for (int i = 0; i < frame->height; i++)
 av_hash_update(hash, &frame->data[0][i * frame->linesize[0]], 
frame->width);
@@ -104,8 +105,8 @@ static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
 (frame->width * frame->height + 2 * (frame->height >> 
desc->log2_chroma_h) * (frame->width >> desc->log2_chroma_w)), sum);
 frame_cnt += 1;
 av_hash_freep(&hash);
-av_free(sum);
 }
+return 0;
 }
 
 int main(int argc, char **argv)
@@ -117,12 +118,12 @@ int main(int argc, char **argv)
 AVPacket *pkt;
 FILE *fd;
 char nal[MAX_SLICES * UINT16_MAX + AV_INPUT_BUFFER_PADDING_SIZE];
-int nals = 0;
+int nals = 0, ret = 0;
 char *p = nal;
 
 if (argc < 4) {
 fprintf(stderr, "Usage: %s   \n", 
argv[0]);
-exit(1);
+return -1;
 }
 
 if (!(threads = strtoul(argv[1], NULL, 0)))
@@ -134,17 +135,19 @@ int main(int argc, char **argv)
 setmode(fileno(stdout), O_BINARY);
 #endif
 
-if (!(pkt = av_packet_alloc()))
-exit(1);
+if (!(pkt = av_packet_alloc())) {
+return -1;
+}
 
 if (!(codec = avcodec_find_decoder(AV_CODEC_ID_H264))) {
 fprintf(stderr, "Codec not found\n");
-exit(1);
+return -1;
 }
 
 if (!(c = avcodec_alloc_context3(codec))) {
 fprintf(stderr, "Could not allocate video codec context\n");
-exit(1);
+ret = -1;
+goto err_avctx;
 }
 
 c->width  = 352;
@@ -154,15 +157,16 @@ int main(int argc, char **argv)
 c->thread_type = FF_THREAD_SLICE;
 c->thread_count = threads;
 
-if (avcodec_open2(c, codec, NULL) < 0) {
+if ((ret = avcodec_open2(c, codec, NULL)) < 0) {
 fprintf(stderr, "Could not open codec\n");
-exit(1);
+goto err_frame;
 }
 
 #if HAVE_THREADS
 if (c->active_thread_type != FF_THREAD_SLICE) {
 fprintf(stderr, "Couldn't activate slice threading: %d\n", 
c->active_thread_type);
-exit(1);
+ret = -1;
+goto err_frame;
 }
 #else
 fprintf(stderr, "WARN: not using threads, only checking decoding slice 
NALUs\n");
@@ -170,34 +174,36 @@ int main(int argc, char **argv)
 
 if (!(frame = av_frame_alloc())) {
 fprintf(stderr, "Could not allocate video frame\n");
-exit(1);
+ret = -1;
+goto err_frame;
 }
 
 if (!(fd = fopen(argv[2], "rb"))) {
 fprintf(stderr, "Couldn't open NALU file: %s\n", argv[2]);
-exit(1);
+ret = -1;
+goto err_fopen;
 }
 
 while(1) {
 uint16_t size = 0;
-ssize_t ret = fread(&size, 1, sizeof(uint16_t), fd);
-if (ret < 0) {
-perror("Couldn't read size");
-exit(1);
-} else if (ret != sizeof(uint16_t))
+size_t ret = fread(&size, 1, sizeof(uint16_t), fd);
+if (ret != sizeof(uint16_t))
 break;
 size = ntohs(size);
 ret = fread(p, 1, size, fd);
-if (ret < 0 || ret != size) {
+if (ret != size) {
 perror("Couldn't read data");
-exit(1);
+goto err;
 }
 p += ret;
 
 if (++nals >= threads) {
+int decret = 

[FFmpeg-devel] [PATCH v2] fate/api-h264-slice-test: use cleaner error handling

2018-10-29 Thread joshdk
From: Josh de Kock 

---
 tests/api/api-h264-slice-test.c | 85 +++--
 1 file changed, 48 insertions(+), 37 deletions(-)

diff --git a/tests/api/api-h264-slice-test.c b/tests/api/api-h264-slice-test.c
index 57e7dc79c3..b3f9f91ab3 100644
--- a/tests/api/api-h264-slice-test.c
+++ b/tests/api/api-h264-slice-test.c
@@ -48,7 +48,7 @@
 
 static int header = 0;
 
-static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
+static int decode(AVCodecContext *dec_ctx, AVFrame *frame,
AVPacket *pkt)
 {
 static uint64_t frame_cnt = 0;
@@ -57,20 +57,20 @@ static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
 ret = avcodec_send_packet(dec_ctx, pkt);
 if (ret < 0) {
 fprintf(stderr, "Error sending a packet for decoding: %s\n", 
av_err2str(ret));
-exit(1);
+return ret;
 }
 
 while (ret >= 0) {
 const AVPixFmtDescriptor *desc;
-char *sum;
+char sum[AV_HASH_MAX_SIZE * 2 + 1];
 struct AVHashContext *hash;
 
 ret = avcodec_receive_frame(dec_ctx, frame);
 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
-return;
+return 0;
 } else if (ret < 0) {
 fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret));
-exit(1);
+return ret;
 }
 
 if (!header) {
@@ -87,9 +87,10 @@ static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
 header = 1;
 }
 desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt);
-av_hash_alloc(&hash, "md5");
+if ((ret = av_hash_alloc(&hash, "md5")) < 0) {
+return ret;
+}
 av_hash_init(hash);
-sum = av_mallocz(av_hash_get_size(hash) * 2 + 1);
 
 for (int i = 0; i < frame->height; i++)
 av_hash_update(hash, &frame->data[0][i * frame->linesize[0]], 
frame->width);
@@ -104,25 +105,25 @@ static void decode(AVCodecContext *dec_ctx, AVFrame 
*frame,
 (frame->width * frame->height + 2 * (frame->height >> 
desc->log2_chroma_h) * (frame->width >> desc->log2_chroma_w)), sum);
 frame_cnt += 1;
 av_hash_freep(&hash);
-av_free(sum);
 }
+return 0;
 }
 
 int main(int argc, char **argv)
 {
-const AVCodec *codec;
+const AVCodec *codec = NULL;
 AVCodecContext *c = NULL;
-AVFrame *frame;
+AVFrame *frame = NULL;
 unsigned int threads;
 AVPacket *pkt;
-FILE *fd;
+FILE *file = NULL;
 char nal[MAX_SLICES * UINT16_MAX + AV_INPUT_BUFFER_PADDING_SIZE];
-int nals = 0;
+int nals = 0, ret = 0;
 char *p = nal;
 
 if (argc < 4) {
 fprintf(stderr, "Usage: %s   \n", 
argv[0]);
-exit(1);
+return -1;
 }
 
 if (!(threads = strtoul(argv[1], NULL, 0)))
@@ -134,17 +135,20 @@ int main(int argc, char **argv)
 setmode(fileno(stdout), O_BINARY);
 #endif
 
-if (!(pkt = av_packet_alloc()))
-exit(1);
+if (!(pkt = av_packet_alloc())) {
+return -1;
+}
 
 if (!(codec = avcodec_find_decoder(AV_CODEC_ID_H264))) {
 fprintf(stderr, "Codec not found\n");
-exit(1);
+ret = -1;
+goto err;
 }
 
 if (!(c = avcodec_alloc_context3(codec))) {
 fprintf(stderr, "Could not allocate video codec context\n");
-exit(1);
+ret = -1;
+goto err;
 }
 
 c->width  = 352;
@@ -154,15 +158,16 @@ int main(int argc, char **argv)
 c->thread_type = FF_THREAD_SLICE;
 c->thread_count = threads;
 
-if (avcodec_open2(c, codec, NULL) < 0) {
+if ((ret = avcodec_open2(c, codec, NULL)) < 0) {
 fprintf(stderr, "Could not open codec\n");
-exit(1);
+goto err;
 }
 
 #if HAVE_THREADS
 if (c->active_thread_type != FF_THREAD_SLICE) {
 fprintf(stderr, "Couldn't activate slice threading: %d\n", 
c->active_thread_type);
-exit(1);
+ret = -1;
+goto err;
 }
 #else
 fprintf(stderr, "WARN: not using threads, only checking decoding slice 
NALUs\n");
@@ -170,34 +175,36 @@ int main(int argc, char **argv)
 
 if (!(frame = av_frame_alloc())) {
 fprintf(stderr, "Could not allocate video frame\n");
-exit(1);
+ret = -1;
+goto err;
 }
 
-if (!(fd = fopen(argv[2], "rb"))) {
+if (!(file = fopen(argv[2], "rb"))) {
 fprintf(stderr, "Couldn't open NALU file: %s\n", argv[2]);
-exit(1);
+ret = -1;
+goto err;
 }
 
 while(1) {
 uint16_t size = 0;
-ssize_t ret = fread(&size, 1, sizeof(uint16_t), fd);
-if (ret < 0) {
-perror("Couldn't read size");
-exit(1);
-} else if (ret != sizeof(uint16_t))
+size_t ret = fread(&size, 1, sizeof(uint16_t), file);
+if (ret != sizeof(uint16_t))
 break;
 size = ntohs(size);
-ret = fread(p, 1, size, fd);
-if (ret < 0 || ret != size) {
+ret = fread(p, 1, size

[FFmpeg-devel] [PATCH v3] fate/api-h264-slice-test: use cleaner error handling

2018-10-30 Thread joshdk
From: Josh de Kock 

Fix ticket #7521
---
 tests/api/api-h264-slice-test.c | 88 +++--
 1 file changed, 51 insertions(+), 37 deletions(-)

diff --git a/tests/api/api-h264-slice-test.c b/tests/api/api-h264-slice-test.c
index 57e7dc79c3..ebc90b5b57 100644
--- a/tests/api/api-h264-slice-test.c
+++ b/tests/api/api-h264-slice-test.c
@@ -48,7 +48,7 @@
 
 static int header = 0;
 
-static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
+static int decode(AVCodecContext *dec_ctx, AVFrame *frame,
AVPacket *pkt)
 {
 static uint64_t frame_cnt = 0;
@@ -57,20 +57,20 @@ static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
 ret = avcodec_send_packet(dec_ctx, pkt);
 if (ret < 0) {
 fprintf(stderr, "Error sending a packet for decoding: %s\n", 
av_err2str(ret));
-exit(1);
+return ret;
 }
 
 while (ret >= 0) {
 const AVPixFmtDescriptor *desc;
-char *sum;
+char sum[AV_HASH_MAX_SIZE * 2 + 1];
 struct AVHashContext *hash;
 
 ret = avcodec_receive_frame(dec_ctx, frame);
 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
-return;
+return 0;
 } else if (ret < 0) {
 fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret));
-exit(1);
+return ret;
 }
 
 if (!header) {
@@ -87,9 +87,10 @@ static void decode(AVCodecContext *dec_ctx, AVFrame *frame,
 header = 1;
 }
 desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt);
-av_hash_alloc(&hash, "md5");
+if ((ret = av_hash_alloc(&hash, "md5")) < 0) {
+return ret;
+}
 av_hash_init(hash);
-sum = av_mallocz(av_hash_get_size(hash) * 2 + 1);
 
 for (int i = 0; i < frame->height; i++)
 av_hash_update(hash, &frame->data[0][i * frame->linesize[0]], 
frame->width);
@@ -104,25 +105,25 @@ static void decode(AVCodecContext *dec_ctx, AVFrame 
*frame,
 (frame->width * frame->height + 2 * (frame->height >> 
desc->log2_chroma_h) * (frame->width >> desc->log2_chroma_w)), sum);
 frame_cnt += 1;
 av_hash_freep(&hash);
-av_free(sum);
 }
+return 0;
 }
 
 int main(int argc, char **argv)
 {
-const AVCodec *codec;
+const AVCodec *codec = NULL;
 AVCodecContext *c = NULL;
-AVFrame *frame;
+AVFrame *frame = NULL;
 unsigned int threads;
 AVPacket *pkt;
-FILE *fd;
+FILE *file = NULL;
 char nal[MAX_SLICES * UINT16_MAX + AV_INPUT_BUFFER_PADDING_SIZE];
-int nals = 0;
+int nals = 0, ret = 0;
 char *p = nal;
 
 if (argc < 4) {
 fprintf(stderr, "Usage: %s   \n", 
argv[0]);
-exit(1);
+return -1;
 }
 
 if (!(threads = strtoul(argv[1], NULL, 0)))
@@ -134,17 +135,20 @@ int main(int argc, char **argv)
 setmode(fileno(stdout), O_BINARY);
 #endif
 
-if (!(pkt = av_packet_alloc()))
-exit(1);
+if (!(pkt = av_packet_alloc())) {
+return -1;
+}
 
 if (!(codec = avcodec_find_decoder(AV_CODEC_ID_H264))) {
 fprintf(stderr, "Codec not found\n");
-exit(1);
+ret = -1;
+goto err;
 }
 
 if (!(c = avcodec_alloc_context3(codec))) {
 fprintf(stderr, "Could not allocate video codec context\n");
-exit(1);
+ret = -1;
+goto err;
 }
 
 c->width  = 352;
@@ -154,15 +158,16 @@ int main(int argc, char **argv)
 c->thread_type = FF_THREAD_SLICE;
 c->thread_count = threads;
 
-if (avcodec_open2(c, codec, NULL) < 0) {
+if ((ret = avcodec_open2(c, codec, NULL)) < 0) {
 fprintf(stderr, "Could not open codec\n");
-exit(1);
+goto err;
 }
 
 #if HAVE_THREADS
 if (c->active_thread_type != FF_THREAD_SLICE) {
 fprintf(stderr, "Couldn't activate slice threading: %d\n", 
c->active_thread_type);
-exit(1);
+ret = -1;
+goto err;
 }
 #else
 fprintf(stderr, "WARN: not using threads, only checking decoding slice 
NALUs\n");
@@ -170,34 +175,39 @@ int main(int argc, char **argv)
 
 if (!(frame = av_frame_alloc())) {
 fprintf(stderr, "Could not allocate video frame\n");
-exit(1);
+ret = -1;
+goto err;
 }
 
-if (!(fd = fopen(argv[2], "rb"))) {
+if (!(file = fopen(argv[2], "rb"))) {
 fprintf(stderr, "Couldn't open NALU file: %s\n", argv[2]);
-exit(1);
+ret = -1;
+goto err;
 }
 
 while(1) {
 uint16_t size = 0;
-ssize_t ret = fread(&size, 1, sizeof(uint16_t), fd);
-if (ret < 0) {
-perror("Couldn't read size");
-exit(1);
-} else if (ret != sizeof(uint16_t))
+
+size_t ret = fread(&size, 1, sizeof(uint16_t), file);
+if (ret != sizeof(uint16_t))
 break;
+
 size = ntohs(size);
-ret = fread(p, 1, size, fd);
-if (ret < 0 || ret != size) {
+
+   

[FFmpeg-devel] [PATCH] h264: Support multi-field closed captions by using AVBufferRef and not resetting per field

2018-08-16 Thread joshdk
From: Kieran Kunhya 

---
This is also useful when CC is fully contained in the first field.

 libavcodec/h264_sei.c   | 15 ---
 libavcodec/h264_sei.h   |  3 +--
 libavcodec/h264_slice.c | 15 ++-
 libavcodec/h264dec.c|  5 +++--
 4 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index 6499086210..43593d34d2 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -51,8 +51,7 @@ void ff_h264_sei_uninit(H264SEIContext *h)
 h->display_orientation.present = 0;
 h->afd.present =  0;
 
-h->a53_caption.a53_caption_size = 0;
-av_freep(&h->a53_caption.a53_caption);
+av_buffer_unref(&h->a53_caption.buf_ref);
 }
 
 static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb,
@@ -169,7 +168,8 @@ static int 
decode_registered_user_data_closed_caption(H264SEIA53Caption *h,
 size -= 2;
 
 if (cc_count && size >= cc_count * 3) {
-const uint64_t new_size = (h->a53_caption_size + cc_count
+int old_size = h->buf_ref ? h->buf_ref->size : 0;
+const uint64_t new_size = (old_size + cc_count
* UINT64_C(3));
 int i, ret;
 
@@ -177,14 +177,15 @@ static int 
decode_registered_user_data_closed_caption(H264SEIA53Caption *h,
 return AVERROR(EINVAL);
 
 /* Allow merging of the cc data from two fields. */
-ret = av_reallocp(&h->a53_caption, new_size);
+ret = av_buffer_realloc(&h->buf_ref, new_size);
 if (ret < 0)
 return ret;
 
+/* Use of av_buffer_realloc assumes buffer is writeable */
 for (i = 0; i < cc_count; i++) {
-h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8);
-h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8);
-h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8);
+h->buf_ref->data[old_size++] = get_bits(gb, 8);
+h->buf_ref->data[old_size++] = get_bits(gb, 8);
+h->buf_ref->data[old_size++] = get_bits(gb, 8);
 }
 
 skip_bits(gb, 8);   // marker_bits
diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h
index a169a10e49..5b7c8ef9d8 100644
--- a/libavcodec/h264_sei.h
+++ b/libavcodec/h264_sei.h
@@ -95,8 +95,7 @@ typedef struct H264SEIAFD {
 } H264SEIAFD;
 
 typedef struct H264SEIA53Caption {
-int a53_caption_size;
-uint8_t *a53_caption;
+AVBufferRef *buf_ref;
 } H264SEIA53Caption;
 
 typedef struct H264SEIUnregistered {
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index ede9a1a6ea..7bbe65878f 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -429,6 +429,12 @@ int ff_h264_update_thread_context(AVCodecContext *dst,
MAX_DELAYED_PIC_COUNT + 2, h, h1);
 
 h->frame_recovered   = h1->frame_recovered;
+if (h1->sei.a53_caption.buf_ref) {
+h->sei.a53_caption.buf_ref = 
av_buffer_ref(h1->sei.a53_caption.buf_ref);
+av_buffer_unref(&h1->sei.a53_caption.buf_ref);
+}
+else
+h->sei.a53_caption.buf_ref = NULL;
 
 if (!h->cur_pic_ptr)
 return 0;
@@ -1269,15 +1275,14 @@ static int h264_export_frame_props(H264Context *h)
 }
 }
 
-if (h->sei.a53_caption.a53_caption) {
+if (h->sei.a53_caption.buf_ref) {
 H264SEIA53Caption *a53 = &h->sei.a53_caption;
 AVFrameSideData *sd = av_frame_new_side_data(cur->f,
  AV_FRAME_DATA_A53_CC,
- a53->a53_caption_size);
+ a53->buf_ref->size);
 if (sd)
-memcpy(sd->data, a53->a53_caption, a53->a53_caption_size);
-av_freep(&a53->a53_caption);
-a53->a53_caption_size = 0;
+memcpy(sd->data, a53->buf_ref->data, a53->buf_ref->size);
+av_buffer_unref(&a53->buf_ref);
 h->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
 }
 
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 7494c7a8f2..8d115fa040 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -609,9 +609,10 @@ static int decode_nal_units(H264Context *h, const uint8_t 
*buf, int buf_size)
 
 if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS)) {
 h->current_slice = 0;
-if (!h->first_field)
+if (!h->first_field) {
 h->cur_pic_ptr = NULL;
-ff_h264_sei_uninit(&h->sei);
+ff_h264_sei_uninit(&h->sei);
+}
 }
 
 if (h->nal_length_size == 4) {
-- 
2.17.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2] h264: Support multi-field closed captions by using AVBufferRef and not resetting per field

2018-08-17 Thread joshdk
From: Kieran Kunhya 

Signed-off-by: Josh de Kock 
---
 libavcodec/h264_sei.c   | 15 ---
 libavcodec/h264_sei.h   |  3 +--
 libavcodec/h264_slice.c | 26 ++
 libavcodec/h264dec.c|  5 +++--
 4 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index 6499086210..43593d34d2 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -51,8 +51,7 @@ void ff_h264_sei_uninit(H264SEIContext *h)
 h->display_orientation.present = 0;
 h->afd.present =  0;
 
-h->a53_caption.a53_caption_size = 0;
-av_freep(&h->a53_caption.a53_caption);
+av_buffer_unref(&h->a53_caption.buf_ref);
 }
 
 static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb,
@@ -169,7 +168,8 @@ static int 
decode_registered_user_data_closed_caption(H264SEIA53Caption *h,
 size -= 2;
 
 if (cc_count && size >= cc_count * 3) {
-const uint64_t new_size = (h->a53_caption_size + cc_count
+int old_size = h->buf_ref ? h->buf_ref->size : 0;
+const uint64_t new_size = (old_size + cc_count
* UINT64_C(3));
 int i, ret;
 
@@ -177,14 +177,15 @@ static int 
decode_registered_user_data_closed_caption(H264SEIA53Caption *h,
 return AVERROR(EINVAL);
 
 /* Allow merging of the cc data from two fields. */
-ret = av_reallocp(&h->a53_caption, new_size);
+ret = av_buffer_realloc(&h->buf_ref, new_size);
 if (ret < 0)
 return ret;
 
+/* Use of av_buffer_realloc assumes buffer is writeable */
 for (i = 0; i < cc_count; i++) {
-h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8);
-h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8);
-h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8);
+h->buf_ref->data[old_size++] = get_bits(gb, 8);
+h->buf_ref->data[old_size++] = get_bits(gb, 8);
+h->buf_ref->data[old_size++] = get_bits(gb, 8);
 }
 
 skip_bits(gb, 8);   // marker_bits
diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h
index a169a10e49..5b7c8ef9d8 100644
--- a/libavcodec/h264_sei.h
+++ b/libavcodec/h264_sei.h
@@ -95,8 +95,7 @@ typedef struct H264SEIAFD {
 } H264SEIAFD;
 
 typedef struct H264SEIA53Caption {
-int a53_caption_size;
-uint8_t *a53_caption;
+AVBufferRef *buf_ref;
 } H264SEIA53Caption;
 
 typedef struct H264SEIUnregistered {
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index ede9a1a6ea..f31c9a2579 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -430,6 +430,15 @@ int ff_h264_update_thread_context(AVCodecContext *dst,
 
 h->frame_recovered   = h1->frame_recovered;
 
+av_buffer_unref(&h->sei.a53_caption.buf_ref);
+h->sei.a53_caption.buf_ref = NULL;
+
+if (h1->sei.a53_caption.buf_ref) {
+h->sei.a53_caption.buf_ref = 
av_buffer_ref(h1->sei.a53_caption.buf_ref);
+if (!h->sei.a53_caption.buf_ref)
+return AVERROR(ENOMEM);
+}
+
 if (!h->cur_pic_ptr)
 return 0;
 
@@ -1269,15 +1278,16 @@ static int h264_export_frame_props(H264Context *h)
 }
 }
 
-if (h->sei.a53_caption.a53_caption) {
+if (h->sei.a53_caption.buf_ref) {
 H264SEIA53Caption *a53 = &h->sei.a53_caption;
-AVFrameSideData *sd = av_frame_new_side_data(cur->f,
- AV_FRAME_DATA_A53_CC,
- a53->a53_caption_size);
-if (sd)
-memcpy(sd->data, a53->a53_caption, a53->a53_caption_size);
-av_freep(&a53->a53_caption);
-a53->a53_caption_size = 0;
+
+AVFrameSideData *sd = av_frame_new_side_data_from_buf(cur->f, 
AV_FRAME_DATA_A53_CC, av_buffer_ref(a53->buf_ref));
+if (sd) {
+av_buffer_unref(&a53->buf_ref);
+} else {
+return AVERROR(ENOMEM);
+}
+
 h->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
 }
 
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 7494c7a8f2..8d115fa040 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -609,9 +609,10 @@ static int decode_nal_units(H264Context *h, const uint8_t 
*buf, int buf_size)
 
 if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS)) {
 h->current_slice = 0;
-if (!h->first_field)
+if (!h->first_field) {
 h->cur_pic_ptr = NULL;
-ff_h264_sei_uninit(&h->sei);
+ff_h264_sei_uninit(&h->sei);
+}
 }
 
 if (h->nal_length_size == 4) {
-- 
2.17.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman

[FFmpeg-devel] [PATCH v3] h264: Support multi-field closed captions by using AVBufferRef and not resetting per field

2018-08-17 Thread joshdk
From: Kieran Kunhya 

Signed-off-by: Josh de Kock 
---
 libavcodec/h264_sei.c   | 15 ---
 libavcodec/h264_sei.h   |  3 +--
 libavcodec/h264_slice.c | 22 ++
 libavcodec/h264dec.c|  5 +++--
 4 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index 6499086210..43593d34d2 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -51,8 +51,7 @@ void ff_h264_sei_uninit(H264SEIContext *h)
 h->display_orientation.present = 0;
 h->afd.present =  0;
 
-h->a53_caption.a53_caption_size = 0;
-av_freep(&h->a53_caption.a53_caption);
+av_buffer_unref(&h->a53_caption.buf_ref);
 }
 
 static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb,
@@ -169,7 +168,8 @@ static int 
decode_registered_user_data_closed_caption(H264SEIA53Caption *h,
 size -= 2;
 
 if (cc_count && size >= cc_count * 3) {
-const uint64_t new_size = (h->a53_caption_size + cc_count
+int old_size = h->buf_ref ? h->buf_ref->size : 0;
+const uint64_t new_size = (old_size + cc_count
* UINT64_C(3));
 int i, ret;
 
@@ -177,14 +177,15 @@ static int 
decode_registered_user_data_closed_caption(H264SEIA53Caption *h,
 return AVERROR(EINVAL);
 
 /* Allow merging of the cc data from two fields. */
-ret = av_reallocp(&h->a53_caption, new_size);
+ret = av_buffer_realloc(&h->buf_ref, new_size);
 if (ret < 0)
 return ret;
 
+/* Use of av_buffer_realloc assumes buffer is writeable */
 for (i = 0; i < cc_count; i++) {
-h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8);
-h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8);
-h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8);
+h->buf_ref->data[old_size++] = get_bits(gb, 8);
+h->buf_ref->data[old_size++] = get_bits(gb, 8);
+h->buf_ref->data[old_size++] = get_bits(gb, 8);
 }
 
 skip_bits(gb, 8);   // marker_bits
diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h
index a169a10e49..5b7c8ef9d8 100644
--- a/libavcodec/h264_sei.h
+++ b/libavcodec/h264_sei.h
@@ -95,8 +95,7 @@ typedef struct H264SEIAFD {
 } H264SEIAFD;
 
 typedef struct H264SEIA53Caption {
-int a53_caption_size;
-uint8_t *a53_caption;
+AVBufferRef *buf_ref;
 } H264SEIA53Caption;
 
 typedef struct H264SEIUnregistered {
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index ede9a1a6ea..58e1aaf02f 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -430,6 +430,13 @@ int ff_h264_update_thread_context(AVCodecContext *dst,
 
 h->frame_recovered   = h1->frame_recovered;
 
+av_buffer_unref(&h->sei.a53_caption.buf_ref);
+if (h1->sei.a53_caption.buf_ref) {
+h->sei.a53_caption.buf_ref = 
av_buffer_ref(h1->sei.a53_caption.buf_ref);
+if (!h->sei.a53_caption.buf_ref)
+return AVERROR(ENOMEM);
+}
+
 if (!h->cur_pic_ptr)
 return 0;
 
@@ -1269,15 +1276,14 @@ static int h264_export_frame_props(H264Context *h)
 }
 }
 
-if (h->sei.a53_caption.a53_caption) {
+if (h->sei.a53_caption.buf_ref) {
 H264SEIA53Caption *a53 = &h->sei.a53_caption;
-AVFrameSideData *sd = av_frame_new_side_data(cur->f,
- AV_FRAME_DATA_A53_CC,
- a53->a53_caption_size);
-if (sd)
-memcpy(sd->data, a53->a53_caption, a53->a53_caption_size);
-av_freep(&a53->a53_caption);
-a53->a53_caption_size = 0;
+
+AVFrameSideData *sd = av_frame_new_side_data_from_buf(cur->f, 
AV_FRAME_DATA_A53_CC, a53->buf_ref);
+if (!sd)
+av_buffer_unref(&a53->buf_ref);
+a53->buf_ref = NULL;
+
 h->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
 }
 
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 7494c7a8f2..8d115fa040 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -609,9 +609,10 @@ static int decode_nal_units(H264Context *h, const uint8_t 
*buf, int buf_size)
 
 if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS)) {
 h->current_slice = 0;
-if (!h->first_field)
+if (!h->first_field) {
 h->cur_pic_ptr = NULL;
-ff_h264_sei_uninit(&h->sei);
+ff_h264_sei_uninit(&h->sei);
+}
 }
 
 if (h->nal_length_size == 4) {
-- 
2.17.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel