From c0f4cf7798541643f43c6ebbaf3f7780c3d3a8df Mon Sep 17 00:00:00 2001 From: Maksalov Boris Date: Fri, 3 Aug 2012 19:50:05 +0200 Subject: [PATCH 1/9] prores: interlaced ProRes encoding Signed-off-by: Luca Barbato --- libavcodec/proresenc.c | 183 ++++++++++++++++++++++++++--------------- 1 file changed, 115 insertions(+), 68 deletions(-) diff --git a/libavcodec/proresenc.c b/libavcodec/proresenc.c index 40644bb3b1..a24b7118c2 100644 --- a/libavcodec/proresenc.c +++ b/libavcodec/proresenc.c @@ -188,7 +188,9 @@ typedef struct ProresContext { int mbs_per_slice; int num_chroma_blocks, chroma_factor; int slices_width; - int num_slices; + int slices_per_picture; + int pictures_per_frame; // 1 for progressive, 2 for interlaced + int cur_picture_idx; int num_planes; int bits_per_mb; int force_quant; @@ -196,7 +198,7 @@ typedef struct ProresContext { char *vendor; int quant_sel; - int frame_size; + int frame_size_upper_bound; int profile; const struct prores_profile *profile_info; @@ -402,10 +404,15 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, int total_size = 0; const uint16_t *src; int slice_width_factor = av_log2(mbs_per_slice); - int num_cblocks, pwidth; + int num_cblocks, pwidth, linesize, line_add; int plane_factor, is_chroma; uint16_t *qmat; + if (ctx->pictures_per_frame == 1) + line_add = 0; + else + line_add = ctx->cur_picture_idx ^ !pic->top_field_first; + if (ctx->force_quant) { qmat = ctx->quants[0]; } else if (quant < MAX_STORED_Q) { @@ -432,12 +439,16 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, num_cblocks = 2; pwidth = avctx->width >> 1; } - src = (const uint16_t*)(pic->data[i] + yp * pic->linesize[i]) + xp; - get_slice_data(ctx, src, pic->linesize[i], xp, yp, - pwidth, avctx->height, ctx->blocks[0], ctx->emu_buf, + linesize = pic->linesize[i] * ctx->pictures_per_frame; + src = (const uint16_t*)(pic->data[i] + yp * linesize + + line_add * pic->linesize[i]) + xp; + + get_slice_data(ctx, src, linesize, xp, yp, + pwidth, avctx->height / ctx->pictures_per_frame, + ctx->blocks[0], ctx->emu_buf, mbs_per_slice, num_cblocks, is_chroma); - sizes[i] = encode_slice_plane(ctx, pb, src, pic->linesize[i], + sizes[i] = encode_slice_plane(ctx, pb, src, linesize, mbs_per_slice, ctx->blocks[0], num_cblocks, plane_factor, qmat); @@ -570,7 +581,12 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, int slice_bits[TRELLIS_WIDTH], slice_score[TRELLIS_WIDTH]; int overquant; uint16_t *qmat; + int linesize[4], line_add; + if (ctx->pictures_per_frame == 1) + line_add = 0; + else + line_add = ctx->cur_picture_idx ^ !pic->top_field_first; mbs = x + mbs_per_slice; for (i = 0; i < ctx->num_planes; i++) { @@ -589,10 +605,14 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, num_cblocks[i] = 2; pwidth = avctx->width >> 1; } - src = (const uint16_t*)(pic->data[i] + yp * pic->linesize[i]) + xp; - get_slice_data(ctx, src, pic->linesize[i], xp, yp, - pwidth, avctx->height, td->blocks[i], td->emu_buf, + linesize[i] = pic->linesize[i] * ctx->pictures_per_frame; + src = (const uint16_t*)(pic->data[i] + yp * linesize[i] + + line_add * pic->linesize[i]) + xp; + + get_slice_data(ctx, src, linesize[i], xp, yp, + pwidth, avctx->height / ctx->pictures_per_frame, + td->blocks[i], td->emu_buf, mbs_per_slice, num_cblocks[i], is_chroma[i]); } @@ -607,7 +627,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, error = 0; for (i = 0; i < ctx->num_planes; i++) { bits += estimate_slice_plane(ctx, &error, i, - src, pic->linesize[i], + src, linesize[i], mbs_per_slice, num_cblocks[i], plane_factor[i], ctx->quants[q], td); @@ -636,7 +656,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, } for (i = 0; i < ctx->num_planes; i++) { bits += estimate_slice_plane(ctx, &error, i, - src, pic->linesize[i], + src, linesize[i], mbs_per_slice, num_cblocks[i], plane_factor[i], qmat, td); @@ -725,12 +745,13 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, int slice_hdr_size = 2 + 2 * (ctx->num_planes - 1); int frame_size, picture_size, slice_size; int pkt_size, ret; + uint8_t frame_flags; *avctx->coded_frame = *pic; avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; - pkt_size = ctx->frame_size + FF_MIN_BUFFER_SIZE; + pkt_size = ctx->frame_size_upper_bound + FF_MIN_BUFFER_SIZE; if ((ret = ff_alloc_packet(pkt, pkt_size)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); @@ -751,7 +772,12 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, bytestream_put_buffer(&buf, ctx->vendor, 4); bytestream_put_be16 (&buf, avctx->width); bytestream_put_be16 (&buf, avctx->height); - bytestream_put_byte (&buf, ctx->chroma_factor << 6); // frame flags + + frame_flags = ctx->chroma_factor << 6; + if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) + frame_flags |= pic->top_field_first ? 0x04 : 0x08; + bytestream_put_byte (&buf, frame_flags); + bytestream_put_byte (&buf, 0); // reserved bytestream_put_byte (&buf, avctx->color_primaries); bytestream_put_byte (&buf, avctx->color_trc); @@ -771,56 +797,64 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, } bytestream_put_be16 (&tmp, buf - orig_buf); // write back frame header size - // picture header - picture_size_pos = buf + 1; - bytestream_put_byte (&buf, 0x40); // picture header size (in bits) - buf += 4; // picture data size will be stored here - bytestream_put_be16 (&buf, ctx->num_slices); // total number of slices - bytestream_put_byte (&buf, av_log2(ctx->mbs_per_slice) << 4); // slice width and height in MBs + for (ctx->cur_picture_idx = 0; + ctx->cur_picture_idx < ctx->pictures_per_frame; + ctx->cur_picture_idx++) { + // picture header + picture_size_pos = buf + 1; + bytestream_put_byte (&buf, 0x40); // picture header size (in bits) + buf += 4; // picture data size will be stored here + bytestream_put_be16 (&buf, ctx->slices_per_picture); + bytestream_put_byte (&buf, av_log2(ctx->mbs_per_slice) << 4); // slice width and height in MBs - // seek table - will be filled during slice encoding - slice_sizes = buf; - buf += ctx->num_slices * 2; + // seek table - will be filled during slice encoding + slice_sizes = buf; + buf += ctx->slices_per_picture * 2; - // slices - if (!ctx->force_quant) { - ret = avctx->execute2(avctx, find_quant_thread, NULL, NULL, - ctx->mb_height); - if (ret) - return ret; - } - - for (y = 0; y < ctx->mb_height; y++) { - int mbs_per_slice = ctx->mbs_per_slice; - for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) { - q = ctx->force_quant ? ctx->force_quant - : ctx->slice_q[mb + y * ctx->slices_width]; - - while (ctx->mb_width - x < mbs_per_slice) - mbs_per_slice >>= 1; - - bytestream_put_byte(&buf, slice_hdr_size << 3); - slice_hdr = buf; - buf += slice_hdr_size - 1; - init_put_bits(&pb, buf, (pkt_size - (buf - orig_buf)) * 8); - encode_slice(avctx, pic, &pb, sizes, x, y, q, mbs_per_slice); - - bytestream_put_byte(&slice_hdr, q); - slice_size = slice_hdr_size + sizes[ctx->num_planes - 1]; - for (i = 0; i < ctx->num_planes - 1; i++) { - bytestream_put_be16(&slice_hdr, sizes[i]); - slice_size += sizes[i]; - } - bytestream_put_be16(&slice_sizes, slice_size); - buf += slice_size - slice_hdr_size; + // slices + if (!ctx->force_quant) { + ret = avctx->execute2(avctx, find_quant_thread, NULL, NULL, + ctx->mb_height); + if (ret) + return ret; } + + for (y = 0; y < ctx->mb_height; y++) { + int mbs_per_slice = ctx->mbs_per_slice; + for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) { + q = ctx->force_quant ? ctx->force_quant + : ctx->slice_q[mb + y * ctx->slices_width]; + + while (ctx->mb_width - x < mbs_per_slice) + mbs_per_slice >>= 1; + + bytestream_put_byte(&buf, slice_hdr_size << 3); + slice_hdr = buf; + buf += slice_hdr_size - 1; + init_put_bits(&pb, buf, (pkt_size - (buf - orig_buf)) * 8); + encode_slice(avctx, pic, &pb, sizes, x, y, q, mbs_per_slice); + + bytestream_put_byte(&slice_hdr, q); + slice_size = slice_hdr_size + sizes[ctx->num_planes - 1]; + for (i = 0; i < ctx->num_planes - 1; i++) { + bytestream_put_be16(&slice_hdr, sizes[i]); + slice_size += sizes[i]; + } + bytestream_put_be16(&slice_sizes, slice_size); + buf += slice_size - slice_hdr_size; + } + } + + if (ctx->pictures_per_frame == 1) + picture_size = buf - picture_size_pos - 6; + else + picture_size = buf - picture_size_pos + 1; + bytestream_put_be32(&picture_size_pos, picture_size); } orig_buf -= 8; frame_size = buf - orig_buf; - picture_size = buf - picture_size_pos - 6; bytestream_put_be32(&orig_buf, frame_size); - bytestream_put_be32(&picture_size_pos, picture_size); pkt->size = frame_size; pkt->flags |= AV_PKT_FLAG_KEY; @@ -855,6 +889,7 @@ static av_cold int encode_init(AVCodecContext *avctx) int mps; int i, j; int min_quant, max_quant; + int interlaced = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT); avctx->bits_per_raw_sample = 10; avctx->coded_frame = avcodec_alloc_frame(); @@ -863,7 +898,8 @@ static av_cold int encode_init(AVCodecContext *avctx) ff_proresdsp_init(&ctx->dsp); ff_init_scantable(ctx->dsp.dct_permutation, &ctx->scantable, - ff_prores_progressive_scan); + interlaced ? ff_prores_interlaced_scan + : ff_prores_progressive_scan); mps = ctx->mbs_per_slice; if (mps & (mps - 1)) { @@ -879,10 +915,16 @@ static av_cold int encode_init(AVCodecContext *avctx) ctx->num_planes = 3; ctx->mb_width = FFALIGN(avctx->width, 16) >> 4; - ctx->mb_height = FFALIGN(avctx->height, 16) >> 4; + + if (interlaced) + ctx->mb_height = FFALIGN(avctx->height, 32) >> 5; + else + ctx->mb_height = FFALIGN(avctx->height, 16) >> 4; + ctx->slices_width = ctx->mb_width / mps; ctx->slices_width += av_popcount(ctx->mb_width - ctx->slices_width * mps); - ctx->num_slices = ctx->mb_height * ctx->slices_width; + ctx->slices_per_picture = ctx->mb_height * ctx->slices_width; + ctx->pictures_per_frame = 1 + interlaced; if (ctx->quant_sel == -1) ctx->quant_mat = prores_quant_matrices[ctx->profile_info->quant]; @@ -898,7 +940,8 @@ static av_cold int encode_init(AVCodecContext *avctx) if (!ctx->force_quant) { if (!ctx->bits_per_mb) { for (i = 0; i < NUM_MB_LIMITS - 1; i++) - if (prores_mb_limits[i] >= ctx->mb_width * ctx->mb_height) + if (prores_mb_limits[i] >= ctx->mb_width * ctx->mb_height * + ctx->pictures_per_frame) break; ctx->bits_per_mb = ctx->profile_info->br_tab[i]; } else if (ctx->bits_per_mb < 128) { @@ -913,7 +956,7 @@ static av_cold int encode_init(AVCodecContext *avctx) ctx->quants[i][j] = ctx->quant_mat[j] * i; } - ctx->slice_q = av_malloc(ctx->num_slices * sizeof(*ctx->slice_q)); + ctx->slice_q = av_malloc(ctx->slices_per_picture * sizeof(*ctx->slice_q)); if (!ctx->slice_q) { encode_close(avctx); return AVERROR(ENOMEM); @@ -959,16 +1002,20 @@ static av_cold int encode_init(AVCodecContext *avctx) ctx->bits_per_mb += ls * 4; } - ctx->frame_size = ctx->num_slices * (2 + 2 * ctx->num_planes - + (2 * mps * ctx->bits_per_mb) / 8) - + 200; + ctx->frame_size_upper_bound = ctx->pictures_per_frame * + ctx->slices_per_picture * + (2 + 2 * ctx->num_planes + + (mps * ctx->bits_per_mb) / 8) + + 200; avctx->codec_tag = ctx->profile_info->tag; - av_log(avctx, AV_LOG_DEBUG, "profile %d, %d slices, %d bits per MB\n", - ctx->profile, ctx->num_slices, ctx->bits_per_mb); - av_log(avctx, AV_LOG_DEBUG, "estimated frame size %d\n", - ctx->frame_size); + av_log(avctx, AV_LOG_DEBUG, + "profile %d, %d slices, interlacing: %s, %d bits per MB\n", + ctx->profile, ctx->slices_per_picture * ctx->pictures_per_frame, + interlaced ? "yes" : "no", ctx->bits_per_mb); + av_log(avctx, AV_LOG_DEBUG, "frame size upper bound: %d\n", + ctx->frame_size_upper_bound); return 0; } From 8b6a5a7923dc4596091acaa9d8219ade39dd2d61 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Sat, 11 Aug 2012 12:41:33 +0200 Subject: [PATCH 2/9] rtmp: Do not send _checkbw calls as notifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The _checkbw calls were changed to use transactionId 0 in commit 82613564 so that servers would not return _result/_error about it. While this is the strict interpretation of the spec, there are servers that return _error about it, even if transactionId was 0. The latest version of EvoStream Media Server (the commercial version of crtmpserver) behaves properly as described, i.e. returning an _error normally but not returning anything when using transactionId 0. The latest version of crtmpserver (right now at least) doesn't behave like this though, it returns an error even if transactionId was 0. There are also other servers that return errors even if transactionId is set to 0. Therefore set a proper transaction id so that the invoke can be tracked and the error properly ignored instead. Signed-off-by: Martin Storsjö --- libavformat/rtmp.h | 9 --------- libavformat/rtmpproto.c | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/libavformat/rtmp.h b/libavformat/rtmp.h index c9aa67e056..b9c5f1e430 100644 --- a/libavformat/rtmp.h +++ b/libavformat/rtmp.h @@ -32,15 +32,6 @@ #define HMAC_IPAD_VAL 0x36 #define HMAC_OPAD_VAL 0x5C -/** - * A non-zero transaction id requires the server to send back - * a _result or _error response. - * Setting it to 0 marks the message as a notification not - * requiring feedback. - */ - -#define RTMP_NOTIFICATION 0 - /** * emulated Flash client version - 9.0.124.2 on Linux * @{ diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 1db3152e8d..150e45a363 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -626,7 +626,7 @@ static int gen_check_bw(URLContext *s, RTMPContext *rt) p = pkt.data; ff_amf_write_string(&p, "_checkbw"); - ff_amf_write_number(&p, RTMP_NOTIFICATION); + ff_amf_write_number(&p, ++rt->nb_invokes); ff_amf_write_null(&p); return rtmp_send_packet(rt, &pkt, 0); From fb7e78089bf04aa73ba53972e8261bf0bbbb121a Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Sat, 11 Aug 2012 12:42:17 +0200 Subject: [PATCH 3/9] rtmp: Gracefully ignore _checkbw errors by tracking them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/rtmpproto.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 150e45a363..a90d9dadb3 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -629,7 +629,7 @@ static int gen_check_bw(URLContext *s, RTMPContext *rt) ff_amf_write_number(&p, ++rt->nb_invokes); ff_amf_write_null(&p); - return rtmp_send_packet(rt, &pkt, 0); + return rtmp_send_packet(rt, &pkt, 1); } /** @@ -1055,15 +1055,27 @@ static int handle_server_bw(URLContext *s, RTMPPacket *pkt) static int handle_invoke_error(URLContext *s, RTMPPacket *pkt) { const uint8_t *data_end = pkt->data + pkt->data_size; + char *tracked_method = NULL; + int level = AV_LOG_ERROR; uint8_t tmpstr[256]; + int ret; + + if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0) + return ret; if (!ff_amf_get_field_value(pkt->data + 9, data_end, "description", tmpstr, sizeof(tmpstr))) { - av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr); - return -1; + if (tracked_method && !strcmp(tracked_method, "_checkbw")) { + /* Ignore _checkbw errors. */ + level = AV_LOG_WARNING; + ret = 0; + } else + ret = -1; + av_log(s, level, "Server error: %s\n", tmpstr); } - return 0; + av_free(tracked_method); + return ret; } static int handle_invoke_result(URLContext *s, RTMPPacket *pkt) From 11928d24fe64c97a5329677ddb9eda44cfca4a56 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 14 Aug 2012 23:17:20 +0200 Subject: [PATCH 4/9] w32pthreads: Add missing #includes to make header compile standalone --- libavcodec/w32pthreads.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/w32pthreads.h b/libavcodec/w32pthreads.h index ae6ceb91f8..8489f715db 100644 --- a/libavcodec/w32pthreads.h +++ b/libavcodec/w32pthreads.h @@ -39,6 +39,9 @@ #include #include +#include "libavutil/internal.h" +#include "libavutil/mem.h" + typedef struct { void *handle; void *(*func)(void* arg); From 4cf4028331f9605cdd3ed5ff7a8ca2fbdaedf7fd Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Thu, 2 Aug 2012 11:23:06 -0700 Subject: [PATCH 5/9] libavresample: add mix level normalization option Provides an option to disable mix level normalization Signed-off-by: Diego Biurrun --- libavresample/audio_mix.c | 4 +++- libavresample/internal.h | 1 + libavresample/options.c | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libavresample/audio_mix.c b/libavresample/audio_mix.c index e8ab2e3ee7..f948c82788 100644 --- a/libavresample/audio_mix.c +++ b/libavresample/audio_mix.c @@ -335,7 +335,9 @@ int ff_audio_mix_init(AVAudioResampleContext *avr) avr->out_channel_layout, avr->center_mix_level, avr->surround_mix_level, - avr->lfe_mix_level, 1, matrix_dbl, + avr->lfe_mix_level, + avr->normalize_mix_level, + matrix_dbl, avr->in_channels, avr->matrix_encoding); if (ret < 0) { diff --git a/libavresample/internal.h b/libavresample/internal.h index 7b7648f0be..006b6fd14a 100644 --- a/libavresample/internal.h +++ b/libavresample/internal.h @@ -45,6 +45,7 @@ struct AVAudioResampleContext { double center_mix_level; /**< center mix level */ double surround_mix_level; /**< surround mix level */ double lfe_mix_level; /**< lfe mix level */ + int normalize_mix_level; /**< enable mix level normalization */ int force_resampling; /**< force resampling */ int filter_size; /**< length of each FIR filter in the resampling filterbank relative to the cutoff frequency */ int phase_shift; /**< log2 of the number of entries in the resampling polyphase filterbank */ diff --git a/libavresample/options.c b/libavresample/options.c index 02e1f86308..e7e0c27c4d 100644 --- a/libavresample/options.c +++ b/libavresample/options.c @@ -47,6 +47,7 @@ static const AVOption options[] = { { "center_mix_level", "Center Mix Level", OFFSET(center_mix_level), AV_OPT_TYPE_DOUBLE, { M_SQRT1_2 }, -32.0, 32.0, PARAM }, { "surround_mix_level", "Surround Mix Level", OFFSET(surround_mix_level), AV_OPT_TYPE_DOUBLE, { M_SQRT1_2 }, -32.0, 32.0, PARAM }, { "lfe_mix_level", "LFE Mix Level", OFFSET(lfe_mix_level), AV_OPT_TYPE_DOUBLE, { 0.0 }, -32.0, 32.0, PARAM }, + { "normalize_mix_level", "Normalize Mix Level", OFFSET(normalize_mix_level), AV_OPT_TYPE_INT, { 1 }, 0, 1, PARAM }, { "force_resampling", "Force Resampling", OFFSET(force_resampling), AV_OPT_TYPE_INT, { 0 }, 0, 1, PARAM }, { "filter_size", "Resampling Filter Size", OFFSET(filter_size), AV_OPT_TYPE_INT, { 16 }, 0, 32, /* ??? */ PARAM }, { "phase_shift", "Resampling Phase Shift", OFFSET(phase_shift), AV_OPT_TYPE_INT, { 10 }, 0, 30, /* ??? */ PARAM }, From be12958937e85b4a280c313d4229c3feba32bf73 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 13 Aug 2012 12:28:59 +0200 Subject: [PATCH 6/9] mpegvideo_mmx_template: drop some commented-out cruft --- libavcodec/x86/mpegvideo_mmx_template.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libavcodec/x86/mpegvideo_mmx_template.c b/libavcodec/x86/mpegvideo_mmx_template.c index 53e09bdbfe..195298d8f3 100644 --- a/libavcodec/x86/mpegvideo_mmx_template.c +++ b/libavcodec/x86/mpegvideo_mmx_template.c @@ -357,13 +357,5 @@ static int RENAME(dct_quantize)(MpegEncContext *s, block[0x3E] = temp_block[0x3E]; block[0x3F] = temp_block[0x3F]; } end: -/* - for(i=0; i Date: Sat, 11 Aug 2012 22:45:53 +0200 Subject: [PATCH 7/9] x86: avcodec: Appropriately name files containing only init functions --- libavcodec/x86/Makefile | 8 ++++---- libavcodec/x86/{ac3dsp_mmx.c => ac3dsp_init.c} | 0 libavcodec/x86/{fft.c => fft_init.c} | 0 libavcodec/x86/{fmtconvert_mmx.c => fmtconvert_init.c} | 0 libavcodec/x86/{h264dsp_mmx.c => h264dsp_init.c} | 0 5 files changed, 4 insertions(+), 4 deletions(-) rename libavcodec/x86/{ac3dsp_mmx.c => ac3dsp_init.c} (100%) rename libavcodec/x86/{fft.c => fft_init.c} (100%) rename libavcodec/x86/{fmtconvert_mmx.c => fmtconvert_init.c} (100%) rename libavcodec/x86/{h264dsp_mmx.c => h264dsp_init.c} (100%) diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile index 57e73d8b2f..4d06685975 100644 --- a/libavcodec/x86/Makefile +++ b/libavcodec/x86/Makefile @@ -5,7 +5,7 @@ OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o MMX-OBJS += x86/dsputil_mmx.o \ x86/fdct_mmx.o \ - x86/fmtconvert_mmx.o \ + x86/fmtconvert_init.o \ x86/idct_mmx_xvid.o \ x86/idct_sse2_xvid.o \ x86/motion_est_mmx.o \ @@ -13,13 +13,13 @@ MMX-OBJS += x86/dsputil_mmx.o \ x86/simple_idct_mmx.o \ MMX-OBJS-$(CONFIG_AAC_DECODER) += x86/sbrdsp_init.o -MMX-OBJS-$(CONFIG_AC3DSP) += x86/ac3dsp_mmx.o +MMX-OBJS-$(CONFIG_AC3DSP) += x86/ac3dsp_init.o MMX-OBJS-$(CONFIG_CAVS_DECODER) += x86/cavsdsp_mmx.o MMX-OBJS-$(CONFIG_DNXHD_ENCODER) += x86/dnxhd_mmx.o MMX-OBJS-$(CONFIG_DWT) += x86/snowdsp_mmx.o MMX-OBJS-$(CONFIG_ENCODERS) += x86/dsputilenc_mmx.o -MMX-OBJS-$(CONFIG_FFT) += x86/fft.o -MMX-OBJS-$(CONFIG_H264DSP) += x86/h264dsp_mmx.o +MMX-OBJS-$(CONFIG_FFT) += x86/fft_init.o +MMX-OBJS-$(CONFIG_H264DSP) += x86/h264dsp_init.o MMX-OBJS-$(CONFIG_H264PRED) += x86/h264_intrapred_init.o MMX-OBJS-$(CONFIG_LPC) += x86/lpc_mmx.o MMX-OBJS-$(CONFIG_MPEGAUDIODSP) += x86/mpegaudiodec_mmx.o diff --git a/libavcodec/x86/ac3dsp_mmx.c b/libavcodec/x86/ac3dsp_init.c similarity index 100% rename from libavcodec/x86/ac3dsp_mmx.c rename to libavcodec/x86/ac3dsp_init.c diff --git a/libavcodec/x86/fft.c b/libavcodec/x86/fft_init.c similarity index 100% rename from libavcodec/x86/fft.c rename to libavcodec/x86/fft_init.c diff --git a/libavcodec/x86/fmtconvert_mmx.c b/libavcodec/x86/fmtconvert_init.c similarity index 100% rename from libavcodec/x86/fmtconvert_mmx.c rename to libavcodec/x86/fmtconvert_init.c diff --git a/libavcodec/x86/h264dsp_mmx.c b/libavcodec/x86/h264dsp_init.c similarity index 100% rename from libavcodec/x86/h264dsp_mmx.c rename to libavcodec/x86/h264dsp_init.c From 661454aa28eef9dfaa6550f1dbc3f195597b1001 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 31 Jul 2012 16:35:18 +0200 Subject: [PATCH 8/9] api-example: use new video encoding API. --- libavcodec/api-example.c | 72 ++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/libavcodec/api-example.c b/libavcodec/api-example.c index 533b6f7cc9..4db92d3702 100644 --- a/libavcodec/api-example.c +++ b/libavcodec/api-example.c @@ -38,6 +38,7 @@ #include "libavcodec/avcodec.h" #include "libavutil/audioconvert.h" +#include "libavutil/imgutils.h" #include "libavutil/mathematics.h" #include "libavutil/samplefmt.h" @@ -316,10 +317,11 @@ static void video_encode_example(const char *filename) { AVCodec *codec; AVCodecContext *c= NULL; - int i, out_size, size, x, y, outbuf_size; + int i, ret, x, y, got_output; FILE *f; AVFrame *picture; - uint8_t *outbuf, *picture_buf; + AVPacket pkt; + uint8_t endcode[] = { 0, 0, 1, 0xb7 }; printf("Video encoding\n"); @@ -356,21 +358,22 @@ static void video_encode_example(const char *filename) exit(1); } - /* alloc image and output buffer */ - outbuf_size = 100000; - outbuf = malloc(outbuf_size); - size = c->width * c->height; - picture_buf = malloc((size * 3) / 2); /* size for YUV 420 */ - - picture->data[0] = picture_buf; - picture->data[1] = picture->data[0] + size; - picture->data[2] = picture->data[1] + size / 4; - picture->linesize[0] = c->width; - picture->linesize[1] = c->width / 2; - picture->linesize[2] = c->width / 2; + ret = av_image_alloc(picture->data, picture->linesize, c->width, c->height, + c->pix_fmt, 32); + if (ret < 0) { + fprintf(stderr, "could not alloc raw picture buffer\n"); + exit(1); + } + picture->format = c->pix_fmt; + picture->width = c->width; + picture->height = c->height; /* encode 1 second of video */ for(i=0;i<25;i++) { + av_init_packet(&pkt); + pkt.data = NULL; // packet data will be allocated by the encoder + pkt.size = 0; + fflush(stdout); /* prepare a dummy image */ /* Y */ @@ -388,33 +391,46 @@ static void video_encode_example(const char *filename) } } + picture->pts = i; + /* encode the image */ - out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture); - printf("encoding frame %3d (size=%5d)\n", i, out_size); - fwrite(outbuf, 1, out_size, f); + ret = avcodec_encode_video2(c, &pkt, picture, &got_output); + if (ret < 0) { + fprintf(stderr, "error encoding frame\n"); + exit(1); + } + + if (got_output) { + printf("encoding frame %3d (size=%5d)\n", i, pkt.size); + fwrite(pkt.data, 1, pkt.size, f); + av_free_packet(&pkt); + } } /* get the delayed frames */ - for(; out_size; i++) { + for (got_output = 1; got_output; i++) { fflush(stdout); - out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL); - printf("write frame %3d (size=%5d)\n", i, out_size); - fwrite(outbuf, 1, out_size, f); + ret = avcodec_encode_video2(c, &pkt, NULL, &got_output); + if (ret < 0) { + fprintf(stderr, "error encoding frame\n"); + exit(1); + } + + if (got_output) { + printf("encoding frame %3d (size=%5d)\n", i, pkt.size); + fwrite(pkt.data, 1, pkt.size, f); + av_free_packet(&pkt); + } } /* add sequence end code to have a real mpeg file */ - outbuf[0] = 0x00; - outbuf[1] = 0x00; - outbuf[2] = 0x01; - outbuf[3] = 0xb7; - fwrite(outbuf, 1, 4, f); + fwrite(endcode, 1, sizeof(endcode), f); fclose(f); - free(picture_buf); - free(outbuf); avcodec_close(c); av_free(c); + av_freep(&picture->data[0]); av_free(picture); printf("\n"); } From 635ac8e1be91e941908f85642e4bbb609e48193f Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Mon, 13 Aug 2012 17:05:00 +0200 Subject: [PATCH 9/9] rtmp: Add support for SWFVerification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Specifies how the server verifies client SWF files before allowing the files to connect to an application. Verifying SWF files is a security measure that prevents someone from creating their own SWF files that can attempt to stream your resources. Signed-off-by: Martin Storsjö --- doc/protocols.texi | 6 ++++ libavformat/rtmpproto.c | 66 +++++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/doc/protocols.texi b/doc/protocols.texi index bf67d89ad3..bdb3e8cae1 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -242,6 +242,12 @@ Name of live stream to subscribe to. By default no value will be sent. It is only sent if the option is specified or if rtmp_live is set to live. +@item rtmp_swfhash +SHA256 hash of the decompressed SWF file (32 bytes). + +@item rtmp_swfsize +Size of the decompressed SWF file, required for SWFVerification. + @item rtmp_swfurl URL of the SWF player for the media. By default no value will be sent. diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index a90d9dadb3..9b85e523c5 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -91,7 +91,11 @@ typedef struct RTMPContext { int nb_invokes; ///< keeps track of invoke messages char* tcurl; ///< url of the target stream char* flashver; ///< version of the flash plugin + char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes) + int swfhash_len; ///< length of the SHA256 hash + int swfsize; ///< size of the decompressed SWF file char* swfurl; ///< url of the swf player + char swfverification[42]; ///< hash of the SWF verification char* pageurl; ///< url of the web page char* subscribe; ///< name of live stream to subscribe int server_bw; ///< server bandwidth @@ -592,6 +596,27 @@ static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt) return rtmp_send_packet(rt, &pkt, 0); } +/** + * Generate SWF verification message and send it to the server. + */ +static int gen_swf_verification(URLContext *s, RTMPContext *rt) +{ + RTMPPacket pkt; + uint8_t *p; + int ret; + + av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n"); + if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, + 0, 44)) < 0) + return ret; + + p = pkt.data; + bytestream_put_be16(&p, 27); + memcpy(p, rt->swfverification, 42); + + return rtmp_send_packet(rt, &pkt, 0); +} + /** * Generate server bandwidth message and send it to the server. */ @@ -776,6 +801,30 @@ static int rtmp_validate_digest(uint8_t *buf, int off) return 0; } +static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt, + uint8_t *buf) +{ + uint8_t *p; + int ret; + + if (rt->swfhash_len != 32) { + av_log(s, AV_LOG_ERROR, + "Hash of the decompressed SWF file is not 32 bytes long.\n"); + return AVERROR(EINVAL); + } + + p = &rt->swfverification[0]; + bytestream_put_byte(&p, 1); + bytestream_put_byte(&p, 1); + bytestream_put_be32(&p, rt->swfsize); + bytestream_put_be32(&p, rt->swfsize); + + if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0) + return ret; + + return 0; +} + /** * Perform handshake with the server by means of exchanging pseudorandom data * signed with HMAC-SHA2 digest. @@ -866,6 +915,14 @@ static int rtmp_handshake(URLContext *s, RTMPContext *rt) } } + /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF, + * key are the last 32 bytes of the server handshake. */ + if (rt->swfsize) { + if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 + + RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0) + return ret; + } + ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0, rtmp_server_key, sizeof(rtmp_server_key), digest); @@ -1001,6 +1058,13 @@ static int handle_ping(URLContext *s, RTMPPacket *pkt) if (t == 6) { if ((ret = gen_pong(s, rt, pkt)) < 0) return ret; + } else if (t == 26) { + if (rt->swfsize) { + if ((ret = gen_swf_verification(s, rt)) < 0) + return ret; + } else { + av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n"); + } } return 0; @@ -1717,6 +1781,8 @@ static const AVOption rtmp_options[] = { {"rtmp_pageurl", "URL of the web page in which the media was embedded. By default no value will be sent.", OFFSET(pageurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC}, {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC}, + {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC}, + {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {0}, 0, INT_MAX, DEC}, {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, { NULL }, diff --git a/libavformat/version.h b/libavformat/version.h index e2cd0c7f05..54185fa5b7 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 54 #define LIBAVFORMAT_VERSION_MINOR 13 -#define LIBAVFORMAT_VERSION_MICRO 2 +#define LIBAVFORMAT_VERSION_MICRO 3 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \