---
This did not save quite as many lines as I had hoped for, but it's a start..
libavcodec/Makefile | 2 +-
libavcodec/h264.c | 358 +++-----------------------------------------------
libavcodec/h264.h | 5 +
libavcodec/h264dec.c | 349 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 375 insertions(+), 339 deletions(-)
create mode 100644 libavcodec/h264dec.c
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 4dc218a..cbdaf33 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -179,7 +179,7 @@ OBJS-$(CONFIG_H263_ENCODER) += mpegvideo_enc.o
mpeg4video.o \
ratecontrol.o h263.o ituh263enc.o \
flvenc.o mpeg12data.o \
mpegvideo.o error_resilience.o
-OBJS-$(CONFIG_H264_DECODER) += h264.o
\
+OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264.o
\
h264_loopfilter.o h264_direct.o
\
cabac.o h264_sei.o h264_ps.o
\
h264_refs.o h264_cavlc.o
h264_cabac.o\
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 787d0dc..66d97d8 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -34,9 +34,7 @@
#include "mpegvideo.h"
#include "h264.h"
#include "h264data.h"
-#include "h264_mvpred.h"
#include "golomb.h"
-#include "mathops.h"
#include "rectangle.h"
#include "thread.h"
#include "vdpau_internal.h"
@@ -1094,7 +1092,7 @@ static void clone_tables(H264Context *dst, H264Context
*src, int i)
* Init context
* Allocate buffers which are not shared amongst multiple threads.
*/
-static int context_init(H264Context *h)
+int ff_h264_context_init(H264Context *h)
{
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->top_borders[0],
h->s.mb_width * 16 * 3 * sizeof(uint8_t) * 2, fail)
@@ -1114,8 +1112,6 @@ fail:
return -1; // free_tables will clean up for us
}
-static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size);
-
static av_cold void common_init(H264Context *h)
{
MpegEncContext *const s = &h->s;
@@ -1161,7 +1157,7 @@ int ff_h264_decode_extradata(H264Context *h)
nalsize = AV_RB16(p) + 2;
if (p - avctx->extradata + nalsize > avctx->extradata_size)
return -1;
- if (decode_nal_units(h, p, nalsize) < 0) {
+ if (ff_h264_decode_nal_units(h, p, nalsize) < 0) {
av_log(avctx, AV_LOG_ERROR,
"Decoding sps %d from avcC failed\n", i);
return -1;
@@ -1174,7 +1170,7 @@ int ff_h264_decode_extradata(H264Context *h)
nalsize = AV_RB16(p) + 2;
if (p - avctx->extradata + nalsize > avctx->extradata_size)
return -1;
- if (decode_nal_units(h, p, nalsize) < 0) {
+ if (ff_h264_decode_nal_units(h, p, nalsize) < 0) {
av_log(avctx, AV_LOG_ERROR,
"Decoding pps %d from avcC failed\n", i);
return -1;
@@ -1185,7 +1181,8 @@ int ff_h264_decode_extradata(H264Context *h)
h->nal_length_size = (avctx->extradata[4] & 0x03) + 1;
} else {
h->is_avc = 0;
- if (decode_nal_units(h, avctx->extradata, avctx->extradata_size) < 0)
+ if (ff_h264_decode_nal_units(h, avctx->extradata,
+ avctx->extradata_size) < 0)
return -1;
}
return 0;
@@ -1244,158 +1241,6 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx)
return 0;
}
-#define IN_RANGE(a, b, size) (((a) >= (b)) && ((a) < ((b) + (size))))
-
-static void copy_picture_range(Picture **to, Picture **from, int count,
- MpegEncContext *new_base,
- MpegEncContext *old_base)
-{
- int i;
-
- for (i = 0; i < count; i++) {
- assert((IN_RANGE(from[i], old_base, sizeof(*old_base)) ||
- IN_RANGE(from[i], old_base->picture,
- sizeof(Picture) * old_base->picture_count) ||
- !from[i]));
- to[i] = REBASE_PICTURE(from[i], new_base, old_base);
- }
-}
-
-static void copy_parameter_set(void **to, void **from, int count, int size)
-{
- int i;
-
- for (i = 0; i < count; i++) {
- if (to[i] && !from[i])
- av_freep(&to[i]);
- else if (from[i] && !to[i])
- to[i] = av_malloc(size);
-
- if (from[i])
- memcpy(to[i], from[i], size);
- }
-}
-
-static int decode_init_thread_copy(AVCodecContext *avctx)
-{
- H264Context *h = avctx->priv_data;
-
- if (!avctx->internal->is_copy)
- return 0;
- memset(h->sps_buffers, 0, sizeof(h->sps_buffers));
- memset(h->pps_buffers, 0, sizeof(h->pps_buffers));
-
- return 0;
-}
-
-#define copy_fields(to, from, start_field, end_field) \
- memcpy(&to->start_field, &from->start_field, \
- (char *)&to->end_field - (char *)&to->start_field)
-
-static int decode_update_thread_context(AVCodecContext *dst,
- const AVCodecContext *src)
-{
- H264Context *h = dst->priv_data, *h1 = src->priv_data;
- MpegEncContext *const s = &h->s, *const s1 = &h1->s;
- int inited = s->context_initialized, err;
- int i;
-
- if (dst == src || !s1->context_initialized)
- return 0;
-
- err = ff_mpeg_update_thread_context(dst, src);
- if (err)
- return err;
-
- // FIXME handle width/height changing
- if (!inited) {
- for (i = 0; i < MAX_SPS_COUNT; i++)
- av_freep(h->sps_buffers + i);
-
- for (i = 0; i < MAX_PPS_COUNT; i++)
- av_freep(h->pps_buffers + i);
-
- // copy all fields after MpegEnc
- memcpy(&h->s + 1, &h1->s + 1,
- sizeof(H264Context) - sizeof(MpegEncContext));
- memset(h->sps_buffers, 0, sizeof(h->sps_buffers));
- memset(h->pps_buffers, 0, sizeof(h->pps_buffers));
- if (ff_h264_alloc_tables(h) < 0) {
- av_log(dst, AV_LOG_ERROR, "Could not allocate memory for h264\n");
- return AVERROR(ENOMEM);
- }
- context_init(h);
-
- for (i = 0; i < 2; i++) {
- h->rbsp_buffer[i] = NULL;
- h->rbsp_buffer_size[i] = 0;
- }
-
- h->thread_context[0] = h;
-
- /* frame_start may not be called for the next thread (if it's decoding
- * a bottom field) so this has to be allocated here */
- h->s.obmc_scratchpad = av_malloc(16 * 6 * s->linesize);
-
- s->dsp.clear_blocks(h->mb);
- s->dsp.clear_blocks(h->mb + (24 * 16 << h->pixel_shift));
- }
-
- // extradata/NAL handling
- h->is_avc = h1->is_avc;
-
- // SPS/PPS
- copy_parameter_set((void **)h->sps_buffers, (void **)h1->sps_buffers,
- MAX_SPS_COUNT, sizeof(SPS));
- h->sps = h1->sps;
- copy_parameter_set((void **)h->pps_buffers, (void **)h1->pps_buffers,
- MAX_PPS_COUNT, sizeof(PPS));
- h->pps = h1->pps;
-
- // Dequantization matrices
- // FIXME these are big - can they be only copied when PPS changes?
- copy_fields(h, h1, dequant4_buffer, dequant4_coeff);
-
- for (i = 0; i < 6; i++)
- h->dequant4_coeff[i] = h->dequant4_buffer[0] +
- (h1->dequant4_coeff[i] -
h1->dequant4_buffer[0]);
-
- for (i = 0; i < 6; i++)
- h->dequant8_coeff[i] = h->dequant8_buffer[0] +
- (h1->dequant8_coeff[i] -
h1->dequant8_buffer[0]);
-
- h->dequant_coeff_pps = h1->dequant_coeff_pps;
-
- // POC timing
- copy_fields(h, h1, poc_lsb, redundant_pic_count);
-
- // reference lists
- copy_fields(h, h1, ref_count, list_count);
- copy_fields(h, h1, ref_list, intra_gb);
- copy_fields(h, h1, short_ref, cabac_init_idc);
-
- copy_picture_range(h->short_ref, h1->short_ref, 32, s, s1);
- copy_picture_range(h->long_ref, h1->long_ref, 32, s, s1);
- copy_picture_range(h->delayed_pic, h1->delayed_pic,
- MAX_DELAYED_PIC_COUNT + 2, s, s1);
-
- h->last_slice_type = h1->last_slice_type;
-
- if (!s->current_picture_ptr)
- return 0;
-
- if (!s->dropable) {
- err = ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index);
- h->prev_poc_msb = h->poc_msb;
- h->prev_poc_lsb = h->poc_lsb;
- }
- h->prev_frame_num_offset = h->frame_num_offset;
- h->prev_frame_num = h->frame_num;
- h->outputed_poc = h->next_outputed_poc;
-
- return err;
-}
-
int ff_h264_frame_start(H264Context *h)
{
MpegEncContext *const s = &h->s;
@@ -1409,7 +1254,7 @@ int ff_h264_frame_start(H264Context *h)
* ff_MPV_frame_start uses pict_type to derive key_frame.
* This is incorrect for H.264; IDR markings must be used.
* Zero here; IDR markings per slice in frame or fields are ORed in later.
- * See decode_nal_units().
+ * See ff_h264_decode_nal_units().
*/
s->current_picture_ptr->f.key_frame = 0;
s->current_picture_ptr->mmco_reset = 0;
@@ -1468,7 +1313,7 @@ int ff_h264_frame_start(H264Context *h)
* @param setup_finished enough NALs have been read that we can call
* ff_thread_finish_setup()
*/
-static void decode_postinit(H264Context *h, int setup_finished)
+void ff_h264_decode_postinit(H264Context *h, int setup_finished)
{
MpegEncContext *const s = &h->s;
Picture *out = s->current_picture_ptr;
@@ -1485,8 +1330,8 @@ static void decode_postinit(H264Context *h, int
setup_finished)
if (cur->field_poc[0] == INT_MAX || cur->field_poc[1] == INT_MAX) {
/* FIXME: if we have two PAFF fields in one packet, we can't start
* the next thread here. If we have one field per packet, we can.
- * The check in decode_nal_units() is not good enough to find this
- * yet, so we assume the worst for now. */
+ * The check in ff_h264_ decode_nal_units() is not good enough to
+ * find this yet, so we assume the worst for now. */
// if (setup_finished)
// ff_thread_finish_setup(s->avctx);
return;
@@ -2602,7 +2447,7 @@ static void idr(H264Context *h)
}
/* forget old pics after a seek */
-static void flush_dpb(AVCodecContext *avctx)
+void ff_h264_flush_dpb(AVCodecContext *avctx)
{
H264Context *h = avctx->priv_data;
int i;
@@ -2739,7 +2584,7 @@ static void init_scan_tables(H264Context *h)
}
}
-static int field_end(H264Context *h, int in_setup)
+int ff_h264_field_end(H264Context *h, int in_setup)
{
MpegEncContext *const s = &h->s;
AVCodecContext *const avctx = s->avctx;
@@ -2886,7 +2731,7 @@ static int decode_slice_header(H264Context *h,
H264Context *h0)
if (first_mb_in_slice == 0) { // FIXME better field boundary detection
if (h0->current_slice && FIELD_PICTURE) {
- field_end(h, 1);
+ ff_h264_field_end(h, 1);
}
h0->current_slice = 0;
@@ -2971,7 +2816,7 @@ static int decode_slice_header(H264Context *h,
H264Context *h0)
return -1; // width / height changed during parallelized decoding
}
free_tables(h, 0);
- flush_dpb(s->avctx);
+ ff_h264_flush_dpb(s->avctx);
ff_MPV_common_end(s);
}
if (!s->context_initialized) {
@@ -3069,8 +2914,9 @@ static int decode_slice_header(H264Context *h,
H264Context *h0)
}
if (!HAVE_THREADS || !(s->avctx->active_thread_type &
FF_THREAD_SLICE)) {
- if (context_init(h) < 0) {
- av_log(h->s.avctx, AV_LOG_ERROR, "context_init() failed.\n");
+ if (ff_h264_context_init(h) < 0) {
+ av_log(h->s.avctx, AV_LOG_ERROR,
+ "ff_h264_context_init() failed.\n");
return -1;
}
} else {
@@ -3088,9 +2934,9 @@ static int decode_slice_header(H264Context *h,
H264Context *h0)
}
for (i = 0; i < s->slice_context_count; i++)
- if (context_init(h->thread_context[i]) < 0) {
+ if (ff_h264_context_init(h->thread_context[i]) < 0) {
av_log(h->s.avctx, AV_LOG_ERROR,
- "context_init() failed.\n");
+ "ff_h264_context_init() failed.\n");
return -1;
}
}
@@ -4144,7 +3990,7 @@ static int execute_decode_slices(H264Context *h, int
context_count)
return 0;
}
-static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
+int ff_h264_decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
{
MpegEncContext *const s = &h->s;
AVCodecContext *const avctx = s->avctx;
@@ -4289,7 +4135,7 @@ again:
if (h->current_slice == 1) {
if (!(s->flags2 & CODEC_FLAG2_CHUNKS))
- decode_postinit(h, nal_index >= nals_needed);
+ ff_h264_decode_postinit(h, nal_index >= nals_needed);
if (s->avctx->hwaccel &&
s->avctx->hwaccel->start_frame(s->avctx, NULL, 0) < 0)
@@ -4449,103 +4295,6 @@ end:
return buf_index;
}
-/**
- * Return the number of bytes consumed for building the current frame.
- */
-static int get_consumed_bytes(MpegEncContext *s, int pos, int buf_size)
-{
- if (pos == 0)
- pos = 1; // avoid infinite loops (i doubt that is needed but
...)
- if (pos + 10 > buf_size)
- pos = buf_size; // oops ;)
-
- return pos;
-}
-
-static int decode_frame(AVCodecContext *avctx, void *data,
- int *data_size, AVPacket *avpkt)
-{
- const uint8_t *buf = avpkt->data;
- int buf_size = avpkt->size;
- H264Context *h = avctx->priv_data;
- MpegEncContext *s = &h->s;
- AVFrame *pict = data;
- int buf_index = 0;
-
- s->flags = avctx->flags;
- s->flags2 = avctx->flags2;
-
- /* end of stream, output what is still in the buffers */
-out:
- if (buf_size == 0) {
- Picture *out;
- int i, out_idx;
-
- s->current_picture_ptr = NULL;
-
- // FIXME factorize this with the output code below
- out = h->delayed_pic[0];
- out_idx = 0;
- for (i = 1;
- h->delayed_pic[i] &&
- !h->delayed_pic[i]->f.key_frame &&
- !h->delayed_pic[i]->mmco_reset;
- i++)
- if (h->delayed_pic[i]->poc < out->poc) {
- out = h->delayed_pic[i];
- out_idx = i;
- }
-
- for (i = out_idx; h->delayed_pic[i]; i++)
- h->delayed_pic[i] = h->delayed_pic[i + 1];
-
- if (out) {
- *data_size = sizeof(AVFrame);
- *pict = out->f;
- }
-
- return buf_index;
- }
-
- buf_index = decode_nal_units(h, buf, buf_size);
- if (buf_index < 0)
- return -1;
-
- if (!s->current_picture_ptr && h->nal_unit_type == NAL_END_SEQUENCE) {
- buf_size = 0;
- goto out;
- }
-
- if (!(s->flags2 & CODEC_FLAG2_CHUNKS) && !s->current_picture_ptr) {
- if (avctx->skip_frame >= AVDISCARD_NONREF)
- return 0;
- av_log(avctx, AV_LOG_ERROR, "no frame!\n");
- return -1;
- }
-
- if (!(s->flags2 & CODEC_FLAG2_CHUNKS) ||
- (s->mb_y >= s->mb_height && s->mb_height)) {
- if (s->flags2 & CODEC_FLAG2_CHUNKS)
- decode_postinit(h, 1);
-
- field_end(h, 0);
-
- if (!h->next_output_pic) {
- /* Wait for second field. */
- *data_size = 0;
- } else {
- *data_size = sizeof(AVFrame);
- *pict = h->next_output_pic->f;
- }
- }
-
- assert(pict->data[0] || !*data_size);
- ff_print_debug_info(s, pict);
- // printf("out %d\n", (int)pict->data[0]);
-
- return get_consumed_bytes(s, buf_index, buf_size);
-}
-
av_cold void ff_h264_free_context(H264Context *h)
{
int i;
@@ -4558,70 +4307,3 @@ av_cold void ff_h264_free_context(H264Context *h)
for (i = 0; i < MAX_PPS_COUNT; i++)
av_freep(h->pps_buffers + i);
}
-
-static av_cold int decode_end(AVCodecContext *avctx)
-{
- H264Context *h = avctx->priv_data;
- MpegEncContext *s = &h->s;
-
- ff_h264_free_context(h);
-
- ff_MPV_common_end(s);
-
- // memset(h, 0, sizeof(H264Context));
-
- return 0;
-}
-
-static const AVProfile profiles[] = {
- { FF_PROFILE_H264_BASELINE, "Baseline" },
- { FF_PROFILE_H264_CONSTRAINED_BASELINE, "Constrained Baseline" },
- { FF_PROFILE_H264_MAIN, "Main" },
- { FF_PROFILE_H264_EXTENDED, "Extended" },
- { FF_PROFILE_H264_HIGH, "High" },
- { FF_PROFILE_H264_HIGH_10, "High 10" },
- { FF_PROFILE_H264_HIGH_10_INTRA, "High 10 Intra" },
- { FF_PROFILE_H264_HIGH_422, "High 4:2:2" },
- { FF_PROFILE_H264_HIGH_422_INTRA, "High 4:2:2 Intra" },
- { FF_PROFILE_H264_HIGH_444, "High 4:4:4" },
- { FF_PROFILE_H264_HIGH_444_PREDICTIVE, "High 4:4:4 Predictive" },
- { FF_PROFILE_H264_HIGH_444_INTRA, "High 4:4:4 Intra" },
- { FF_PROFILE_H264_CAVLC_444, "CAVLC 4:4:4" },
- { FF_PROFILE_UNKNOWN },
-};
-
-AVCodec ff_h264_decoder = {
- .name = "h264",
- .type = AVMEDIA_TYPE_VIDEO,
- .id = CODEC_ID_H264,
- .priv_data_size = sizeof(H264Context),
- .init = ff_h264_decode_init,
- .close = decode_end,
- .decode = decode_frame,
- .capabilities = /*CODEC_CAP_DRAW_HORIZ_BAND |*/ CODEC_CAP_DR1 |
- CODEC_CAP_DELAY | CODEC_CAP_SLICE_THREADS |
- CODEC_CAP_FRAME_THREADS,
- .flush = flush_dpb,
- .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC /
MPEG-4 part 10"),
- .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
- .update_thread_context =
ONLY_IF_THREADS_ENABLED(decode_update_thread_context),
- .profiles = NULL_IF_CONFIG_SMALL(profiles),
-};
-
-#if CONFIG_H264_VDPAU_DECODER
-AVCodec ff_h264_vdpau_decoder = {
- .name = "h264_vdpau",
- .type = AVMEDIA_TYPE_VIDEO,
- .id = CODEC_ID_H264,
- .priv_data_size = sizeof(H264Context),
- .init = ff_h264_decode_init,
- .close = decode_end,
- .decode = decode_frame,
- .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY |
CODEC_CAP_HWACCEL_VDPAU,
- .flush = flush_dpb,
- .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4
part 10 (VDPAU acceleration)"),
- .pix_fmts = (const enum PixelFormat[]) { PIX_FMT_VDPAU_H264,
- PIX_FMT_NONE},
- .profiles = NULL_IF_CONFIG_SMALL(profiles),
-};
-#endif
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index 99c46cc..2af6acf 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -662,8 +662,13 @@ int ff_h264_check_intra_pred_mode(H264Context *h, int
mode, int is_chroma);
void ff_h264_hl_decode_mb(H264Context *h);
int ff_h264_frame_start(H264Context *h);
int ff_h264_decode_extradata(H264Context *h);
+int ff_h264_decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size);
av_cold int ff_h264_decode_init(AVCodecContext *avctx);
av_cold void ff_h264_decode_init_vlc(void);
+int ff_h264_context_init(H264Context *h);
+void ff_h264_decode_postinit(H264Context *h, int setup_finished);
+void ff_h264_flush_dpb(AVCodecContext *avctx);
+int ff_h264_field_end(H264Context *h, int in_setup);
/**
* Decode a macroblock
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
new file mode 100644
index 0000000..e911c4e
--- /dev/null
+++ b/libavcodec/h264dec.c
@@ -0,0 +1,349 @@
+/*
+ * H.26L/H.264/AVC/JVT/14496-10/... decoder
+ * Copyright (c) 2003 Michael Niedermayer <[email protected]>
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * H.264 / AVC / MPEG4 part10 decoder
+ * @author Michael Niedermayer <[email protected]>
+ */
+
+#include "avcodec.h"
+#include "mpegvideo.h"
+#include "h264.h"
+
+// #undef NDEBUG
+#include <assert.h>
+
+#define IN_RANGE(a, b, size) (((a) >= (b)) && ((a) < ((b) + (size))))
+
+static void copy_picture_range(Picture **to, Picture **from, int count,
+ MpegEncContext *new_base,
+ MpegEncContext *old_base)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ assert((IN_RANGE(from[i], old_base, sizeof(*old_base)) ||
+ IN_RANGE(from[i], old_base->picture,
+ sizeof(Picture) * old_base->picture_count) ||
+ !from[i]));
+ to[i] = REBASE_PICTURE(from[i], new_base, old_base);
+ }
+}
+
+static void copy_parameter_set(void **to, void **from, int count, int size)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (to[i] && !from[i])
+ av_freep(&to[i]);
+ else if (from[i] && !to[i])
+ to[i] = av_malloc(size);
+
+ if (from[i])
+ memcpy(to[i], from[i], size);
+ }
+}
+
+static int decode_init_thread_copy(AVCodecContext *avctx)
+{
+ H264Context *h = avctx->priv_data;
+
+ if (!avctx->internal->is_copy)
+ return 0;
+ memset(h->sps_buffers, 0, sizeof(h->sps_buffers));
+ memset(h->pps_buffers, 0, sizeof(h->pps_buffers));
+
+ return 0;
+}
+
+#define copy_fields(to, from, start_field, end_field) \
+ memcpy(&to->start_field, &from->start_field, \
+ (char *)&to->end_field - (char *)&to->start_field)
+
+static int decode_update_thread_context(AVCodecContext *dst,
+ const AVCodecContext *src)
+{
+ H264Context *h = dst->priv_data, *h1 = src->priv_data;
+ MpegEncContext *const s = &h->s, *const s1 = &h1->s;
+ int inited = s->context_initialized, err;
+ int i;
+
+ if (dst == src || !s1->context_initialized)
+ return 0;
+
+ err = ff_mpeg_update_thread_context(dst, src);
+ if (err)
+ return err;
+
+ // FIXME handle width/height changing
+ if (!inited) {
+ for (i = 0; i < MAX_SPS_COUNT; i++)
+ av_freep(h->sps_buffers + i);
+
+ for (i = 0; i < MAX_PPS_COUNT; i++)
+ av_freep(h->pps_buffers + i);
+
+ // copy all fields after MpegEnc
+ memcpy(&h->s + 1, &h1->s + 1,
+ sizeof(H264Context) - sizeof(MpegEncContext));
+ memset(h->sps_buffers, 0, sizeof(h->sps_buffers));
+ memset(h->pps_buffers, 0, sizeof(h->pps_buffers));
+ if (ff_h264_alloc_tables(h) < 0) {
+ av_log(dst, AV_LOG_ERROR, "Could not allocate memory for h264\n");
+ return AVERROR(ENOMEM);
+ }
+ ff_h264_context_init(h);
+
+ for (i = 0; i < 2; i++) {
+ h->rbsp_buffer[i] = NULL;
+ h->rbsp_buffer_size[i] = 0;
+ }
+
+ h->thread_context[0] = h;
+
+ /* frame_start may not be called for the next thread (if it's decoding
+ * a bottom field) so this has to be allocated here */
+ h->s.obmc_scratchpad = av_malloc(16 * 6 * s->linesize);
+
+ s->dsp.clear_blocks(h->mb);
+ s->dsp.clear_blocks(h->mb + (24 * 16 << h->pixel_shift));
+ }
+
+ // extradata/NAL handling
+ h->is_avc = h1->is_avc;
+
+ // SPS/PPS
+ copy_parameter_set((void **)h->sps_buffers, (void **)h1->sps_buffers,
+ MAX_SPS_COUNT, sizeof(SPS));
+ h->sps = h1->sps;
+ copy_parameter_set((void **)h->pps_buffers, (void **)h1->pps_buffers,
+ MAX_PPS_COUNT, sizeof(PPS));
+ h->pps = h1->pps;
+
+ // Dequantization matrices
+ // FIXME these are big - can they be only copied when PPS changes?
+ copy_fields(h, h1, dequant4_buffer, dequant4_coeff);
+
+ for (i = 0; i < 6; i++)
+ h->dequant4_coeff[i] = h->dequant4_buffer[0] +
+ (h1->dequant4_coeff[i] -
h1->dequant4_buffer[0]);
+
+ for (i = 0; i < 6; i++)
+ h->dequant8_coeff[i] = h->dequant8_buffer[0] +
+ (h1->dequant8_coeff[i] -
h1->dequant8_buffer[0]);
+
+ h->dequant_coeff_pps = h1->dequant_coeff_pps;
+
+ // POC timing
+ copy_fields(h, h1, poc_lsb, redundant_pic_count);
+
+ // reference lists
+ copy_fields(h, h1, ref_count, list_count);
+ copy_fields(h, h1, ref_list, intra_gb);
+ copy_fields(h, h1, short_ref, cabac_init_idc);
+
+ copy_picture_range(h->short_ref, h1->short_ref, 32, s, s1);
+ copy_picture_range(h->long_ref, h1->long_ref, 32, s, s1);
+ copy_picture_range(h->delayed_pic, h1->delayed_pic,
+ MAX_DELAYED_PIC_COUNT + 2, s, s1);
+
+ h->last_slice_type = h1->last_slice_type;
+
+ if (!s->current_picture_ptr)
+ return 0;
+
+ if (!s->dropable) {
+ err = ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index);
+ h->prev_poc_msb = h->poc_msb;
+ h->prev_poc_lsb = h->poc_lsb;
+ }
+ h->prev_frame_num_offset = h->frame_num_offset;
+ h->prev_frame_num = h->frame_num;
+ h->outputed_poc = h->next_outputed_poc;
+
+ return err;
+}
+
+/**
+ * Return the number of bytes consumed for building the current frame.
+ */
+static int get_consumed_bytes(MpegEncContext *s, int pos, int buf_size)
+{
+ if (pos == 0)
+ pos = 1; // avoid infinite loops (i doubt that is needed but
...)
+ if (pos + 10 > buf_size)
+ pos = buf_size; // oops ;)
+
+ return pos;
+}
+
+static int decode_frame(AVCodecContext *avctx, void *data,
+ int *data_size, AVPacket *avpkt)
+{
+ const uint8_t *buf = avpkt->data;
+ int buf_size = avpkt->size;
+ H264Context *h = avctx->priv_data;
+ MpegEncContext *s = &h->s;
+ AVFrame *pict = data;
+ int buf_index = 0;
+
+ s->flags = avctx->flags;
+ s->flags2 = avctx->flags2;
+
+ /* end of stream, output what is still in the buffers */
+out:
+ if (buf_size == 0) {
+ Picture *out;
+ int i, out_idx;
+
+ s->current_picture_ptr = NULL;
+
+ // FIXME factorize this with the output code below
+ out = h->delayed_pic[0];
+ out_idx = 0;
+ for (i = 1;
+ h->delayed_pic[i] &&
+ !h->delayed_pic[i]->f.key_frame &&
+ !h->delayed_pic[i]->mmco_reset;
+ i++)
+ if (h->delayed_pic[i]->poc < out->poc) {
+ out = h->delayed_pic[i];
+ out_idx = i;
+ }
+
+ for (i = out_idx; h->delayed_pic[i]; i++)
+ h->delayed_pic[i] = h->delayed_pic[i + 1];
+
+ if (out) {
+ *data_size = sizeof(AVFrame);
+ *pict = out->f;
+ }
+
+ return buf_index;
+ }
+
+ buf_index = ff_h264_decode_nal_units(h, buf, buf_size);
+ if (buf_index < 0)
+ return -1;
+
+ if (!s->current_picture_ptr && h->nal_unit_type == NAL_END_SEQUENCE) {
+ buf_size = 0;
+ goto out;
+ }
+
+ if (!(s->flags2 & CODEC_FLAG2_CHUNKS) && !s->current_picture_ptr) {
+ if (avctx->skip_frame >= AVDISCARD_NONREF)
+ return 0;
+ av_log(avctx, AV_LOG_ERROR, "no frame!\n");
+ return -1;
+ }
+
+ if (!(s->flags2 & CODEC_FLAG2_CHUNKS) ||
+ (s->mb_y >= s->mb_height && s->mb_height)) {
+ if (s->flags2 & CODEC_FLAG2_CHUNKS)
+ ff_h264_decode_postinit(h, 1);
+
+ ff_h264_field_end(h, 0);
+
+ if (!h->next_output_pic) {
+ /* Wait for second field. */
+ *data_size = 0;
+ } else {
+ *data_size = sizeof(AVFrame);
+ *pict = h->next_output_pic->f;
+ }
+ }
+
+ assert(pict->data[0] || !*data_size);
+ ff_print_debug_info(s, pict);
+ // printf("out %d\n", (int)pict->data[0]);
+
+ return get_consumed_bytes(s, buf_index, buf_size);
+}
+
+static av_cold int decode_end(AVCodecContext *avctx)
+{
+ H264Context *h = avctx->priv_data;
+ MpegEncContext *s = &h->s;
+
+ ff_h264_free_context(h);
+
+ ff_MPV_common_end(s);
+
+ // memset(h, 0, sizeof(H264Context));
+
+ return 0;
+}
+
+static const AVProfile profiles[] = {
+ { FF_PROFILE_H264_BASELINE, "Baseline" },
+ { FF_PROFILE_H264_CONSTRAINED_BASELINE, "Constrained Baseline" },
+ { FF_PROFILE_H264_MAIN, "Main" },
+ { FF_PROFILE_H264_EXTENDED, "Extended" },
+ { FF_PROFILE_H264_HIGH, "High" },
+ { FF_PROFILE_H264_HIGH_10, "High 10" },
+ { FF_PROFILE_H264_HIGH_10_INTRA, "High 10 Intra" },
+ { FF_PROFILE_H264_HIGH_422, "High 4:2:2" },
+ { FF_PROFILE_H264_HIGH_422_INTRA, "High 4:2:2 Intra" },
+ { FF_PROFILE_H264_HIGH_444, "High 4:4:4" },
+ { FF_PROFILE_H264_HIGH_444_PREDICTIVE, "High 4:4:4 Predictive" },
+ { FF_PROFILE_H264_HIGH_444_INTRA, "High 4:4:4 Intra" },
+ { FF_PROFILE_H264_CAVLC_444, "CAVLC 4:4:4" },
+ { FF_PROFILE_UNKNOWN },
+};
+
+AVCodec ff_h264_decoder = {
+ .name = "h264",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = CODEC_ID_H264,
+ .priv_data_size = sizeof(H264Context),
+ .init = ff_h264_decode_init,
+ .close = decode_end,
+ .decode = decode_frame,
+ .capabilities = /*CODEC_CAP_DRAW_HORIZ_BAND |*/ CODEC_CAP_DR1 |
+ CODEC_CAP_DELAY | CODEC_CAP_SLICE_THREADS |
+ CODEC_CAP_FRAME_THREADS,
+ .flush = ff_h264_flush_dpb,
+ .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC /
MPEG-4 part 10"),
+ .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
+ .update_thread_context =
ONLY_IF_THREADS_ENABLED(decode_update_thread_context),
+ .profiles = NULL_IF_CONFIG_SMALL(profiles),
+};
+
+#if CONFIG_H264_VDPAU_DECODER
+AVCodec ff_h264_vdpau_decoder = {
+ .name = "h264_vdpau",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = CODEC_ID_H264,
+ .priv_data_size = sizeof(H264Context),
+ .init = ff_h264_decode_init,
+ .close = decode_end,
+ .decode = decode_frame,
+ .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY |
CODEC_CAP_HWACCEL_VDPAU,
+ .flush = ff_h264_flush_dpb,
+ .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4
part 10 (VDPAU acceleration)"),
+ .pix_fmts = (const enum PixelFormat[]) { PIX_FMT_VDPAU_H264,
+ PIX_FMT_NONE},
+ .profiles = NULL_IF_CONFIG_SMALL(profiles),
+};
+#endif
--
1.7.1
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel