diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-04-17 22:18:21 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-04-18 00:28:06 +0200 |
commit | 123272374180d8dc3ce9dff50f0c77d5b3b3341f (patch) | |
tree | 2c2add85161e74ebe6d4301a6607adc521112582 | |
parent | a66675268f63dd6794ce946c7edbcb8b49ae0f13 (diff) | |
parent | 0f96f0d9968a767ead3aec823fcdfb78f26f7be7 (diff) | |
download | ffmpeg-123272374180d8dc3ce9dff50f0c77d5b3b3341f.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
aacenc: Fix issues with huge values of bit_rate.
dv_tablegen: Drop unnecessary av_unused attribute from dv_vlc_map_tableinit().
proresenc: multithreaded quantiser search
riff: use bps instead of bits_per_coded_sample in the WAVEFORMATEXTENSIBLE header
avconv: only set the "channels" option when it exists for the specified input format
avplay: update get_buffer to be inline with avconv
aacdec: More robust output configuration.
faac: Fix multi-channel ordering
faac: Add .channel_layouts
rtmp: Support 'rtmp_playpath', an option which overrides the stream identifier
rtmp: Support 'rtmp_app', an option which overrides the name of application
avutil: add better documentation for AVSampleFormat
Conflicts:
libavcodec/aac.h
libavcodec/aacdec.c
libavcodec/aacenc.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | ffmpeg.c | 12 | ||||
-rw-r--r-- | ffplay.c | 4 | ||||
-rw-r--r-- | libavcodec/aac.h | 15 | ||||
-rw-r--r-- | libavcodec/aacdec.c | 263 | ||||
-rw-r--r-- | libavcodec/aacenc.c | 4 | ||||
-rw-r--r-- | libavcodec/aacsbr.c | 12 | ||||
-rw-r--r-- | libavcodec/dv_tablegen.h | 3 | ||||
-rw-r--r-- | libavcodec/libfaac.c | 30 | ||||
-rw-r--r-- | libavcodec/proresenc_kostya.c | 161 | ||||
-rw-r--r-- | libavformat/rtmpproto.c | 67 | ||||
-rw-r--r-- | libavutil/samplefmt.h | 27 |
11 files changed, 403 insertions, 195 deletions
@@ -4189,8 +4189,16 @@ static int opt_input_file(OptionsContext *o, const char *opt, const char *filena av_dict_set(&format_opts, "sample_rate", buf, 0); } if (o->nb_audio_channels) { - snprintf(buf, sizeof(buf), "%d", o->audio_channels[o->nb_audio_channels - 1].u.i); - av_dict_set(&format_opts, "channels", buf, 0); + /* because we set audio_channels based on both the "ac" and + * "channel_layout" options, we need to check that the specified + * demuxer actually has the "channels" option before setting it */ + if (file_iformat && file_iformat->priv_class && + av_opt_find(&file_iformat->priv_class, "channels", NULL, 0, + AV_OPT_SEARCH_FAKE_OBJ)) { + snprintf(buf, sizeof(buf), "%d", + o->audio_channels[o->nb_audio_channels - 1].u.i); + av_dict_set(&format_opts, "channels", buf, 0); + } } if (o->nb_frame_rates) { av_dict_set(&format_opts, "framerate", o->frame_rates[o->nb_frame_rates - 1].u.str, 0); @@ -1600,6 +1600,10 @@ static int input_get_buffer(AVCodecContext *codec, AVFrame *pic) pic->opaque = ref; pic->type = FF_BUFFER_TYPE_USER; pic->reordered_opaque = codec->reordered_opaque; + pic->width = codec->width; + pic->height = codec->height; + pic->format = codec->pix_fmt; + pic->sample_aspect_ratio = codec->sample_aspect_ratio; if (codec->pkt) pic->pkt_pts = codec->pkt->pts; else pic->pkt_pts = AV_NOPTS_VALUE; return 0; diff --git a/libavcodec/aac.h b/libavcodec/aac.h index a45e758f6e..9c5c6c044a 100644 --- a/libavcodec/aac.h +++ b/libavcodec/aac.h @@ -112,6 +112,15 @@ enum OCStatus { OC_LOCKED, ///< Output configuration locked in place }; +typedef struct { + MPEG4AudioConfig m4ac; + uint8_t layout_map[MAX_ELEM_ID*4][3]; + int layout_map_tags; + int channels; + uint64_t channel_layout; + enum OCStatus status; +} OutputConfiguration; + /** * Predictor State */ @@ -254,8 +263,6 @@ typedef struct { AVCodecContext *avctx; AVFrame frame; - MPEG4AudioConfig m4ac; - int is_saved; ///< Set if elements have stored overlap from previous frame. DynamicRangeControl che_drc; @@ -263,8 +270,6 @@ typedef struct { * @name Channel element related data * @{ */ - uint8_t layout_map[MAX_ELEM_ID*4][3]; - int layout_map_tags; ChannelElement *che[4][MAX_ELEM_ID]; ChannelElement *tag_che_map[4][MAX_ELEM_ID]; int tags_mapped; @@ -299,7 +304,7 @@ typedef struct { DECLARE_ALIGNED(32, float, temp)[128]; - enum OCStatus output_configured; + OutputConfiguration oc[2]; int warned_num_aac_frames; } AACContext; diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c index 57ea65eecd..4725343bfd 100644 --- a/libavcodec/aacdec.c +++ b/libavcodec/aacdec.c @@ -149,13 +149,13 @@ static av_cold int che_configure(AACContext *ac, ff_aac_sbr_ctx_init(ac, &ac->che[type][id]->sbr); } if (type != TYPE_CCE) { - if (*channels >= MAX_CHANNELS - (type == TYPE_CPE || (type == TYPE_SCE && ac->m4ac.ps == 1))) { + if (*channels >= MAX_CHANNELS - (type == TYPE_CPE || (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1))) { av_log(ac->avctx, AV_LOG_ERROR, "Too many channels\n"); return AVERROR_INVALIDDATA; } ac->output_data[(*channels)++] = ac->che[type][id]->ch[0].ret; if (type == TYPE_CPE || - (type == TYPE_SCE && ac->m4ac.ps == 1)) { + (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1)) { ac->output_data[(*channels)++] = ac->che[type][id]->ch[1].ret; } } @@ -355,11 +355,38 @@ static uint64_t sniff_channel_order(uint8_t (*layout_map)[3], int tags) } /** + * Save current output configuration if and only if it has been locked. + */ +static void push_output_configuration(AACContext *ac) { + if (ac->oc[1].status == OC_LOCKED) { + ac->oc[0] = ac->oc[1]; + } + ac->oc[1].status = OC_NONE; +} + +/** + * Restore the previous output configuration if and only if the current + * configuration is unlocked. + */ +static void pop_output_configuration(AACContext *ac) { + if (ac->oc[1].status != OC_LOCKED) { + if (ac->oc[0].status == OC_LOCKED) { + ac->oc[1] = ac->oc[0]; + ac->avctx->channels = ac->oc[1].channels; + ac->avctx->channel_layout = ac->oc[1].channel_layout; + }else{ + ac->avctx->channels = 0; + ac->avctx->channel_layout = 0; + } + } +} + +/** * Configure output channel order based on the current program configuration element. * * @return Returns error status. 0 - OK, !0 - error */ -static av_cold int output_configure(AACContext *ac, +static int output_configure(AACContext *ac, uint8_t layout_map[MAX_ELEM_ID*4][3], int tags, int channel_config, enum OCStatus oc_type) { @@ -367,9 +394,9 @@ static av_cold int output_configure(AACContext *ac, int i, channels = 0, ret; uint64_t layout = 0; - if (ac->layout_map != layout_map) { - memcpy(ac->layout_map, layout_map, tags * sizeof(layout_map[0])); - ac->layout_map_tags = tags; + if (ac->oc[1].layout_map != layout_map) { + memcpy(ac->oc[1].layout_map, layout_map, tags * sizeof(layout_map[0])); + ac->oc[1].layout_map_tags = tags; } // Try to sniff a reasonable channel order, otherwise output the @@ -389,8 +416,9 @@ static av_cold int output_configure(AACContext *ac, memcpy(ac->tag_che_map, ac->che, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0])); if (layout) avctx->channel_layout = layout; - avctx->channels = channels; - ac->output_configured = oc_type; + ac->oc[1].channel_layout = layout; + avctx->channels = ac->oc[1].channels = channels; + ac->oc[1].status = oc_type; return 0; } @@ -418,7 +446,7 @@ static void flush(AVCodecContext *avctx) * * @return Returns error status. 0 - OK, !0 - error */ -static av_cold int set_default_channel_config(AVCodecContext *avctx, +static int set_default_channel_config(AVCodecContext *avctx, uint8_t (*layout_map)[3], int *tags, int channel_config) @@ -436,13 +464,14 @@ static av_cold int set_default_channel_config(AVCodecContext *avctx, static ChannelElement *get_che(AACContext *ac, int type, int elem_id) { // For PCE based channel configurations map the channels solely based on tags. - if (!ac->m4ac.chan_config) { + if (!ac->oc[1].m4ac.chan_config) { return ac->tag_che_map[type][elem_id]; } // Allow single CPE stereo files to be signalled with mono configuration. - if (!ac->tags_mapped && type == TYPE_CPE && ac->m4ac.chan_config == 1) { + if (!ac->tags_mapped && type == TYPE_CPE && ac->oc[1].m4ac.chan_config == 1) { uint8_t layout_map[MAX_ELEM_ID*4][3]; int layout_map_tags; + push_output_configuration(ac); if (set_default_channel_config(ac->avctx, layout_map, &layout_map_tags, 2) < 0) @@ -451,10 +480,25 @@ static ChannelElement *get_che(AACContext *ac, int type, int elem_id) 2, OC_TRIAL_FRAME) < 0) return NULL; - ac->m4ac.chan_config = 2; + ac->oc[1].m4ac.chan_config = 2; + } + // And vice-versa + if (!ac->tags_mapped && type == TYPE_SCE && ac->oc[1].m4ac.chan_config == 2) { + uint8_t layout_map[MAX_ELEM_ID*4][3]; + int layout_map_tags; + push_output_configuration(ac); + + if (set_default_channel_config(ac->avctx, layout_map, &layout_map_tags, + 1) < 0) + return NULL; + if (output_configure(ac, layout_map, layout_map_tags, + 1, OC_TRIAL_FRAME) < 0) + return NULL; + + ac->oc[1].m4ac.chan_config = 1; } // For indexed channel configurations map the channels solely based on position. - switch (ac->m4ac.chan_config) { + switch (ac->oc[1].m4ac.chan_config) { case 7: if (ac->tags_mapped == 3 && type == TYPE_CPE) { ac->tags_mapped++; @@ -464,7 +508,7 @@ static ChannelElement *get_che(AACContext *ac, int type, int elem_id) /* Some streams incorrectly code 5.1 audio as SCE[0] CPE[0] CPE[1] SCE[1] instead of SCE[0] CPE[0] CPE[1] LFE[0]. If we seem to have encountered such a stream, transfer the LFE[0] element to the SCE[1]'s mapping */ - if (ac->tags_mapped == tags_per_config[ac->m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) { + if (ac->tags_mapped == tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) { ac->tags_mapped++; return ac->tag_che_map[type][elem_id] = ac->che[TYPE_LFE][0]; } @@ -474,16 +518,16 @@ static ChannelElement *get_che(AACContext *ac, int type, int elem_id) return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][1]; } case 4: - if (ac->tags_mapped == 2 && ac->m4ac.chan_config == 4 && type == TYPE_SCE) { + if (ac->tags_mapped == 2 && ac->oc[1].m4ac.chan_config == 4 && type == TYPE_SCE) { ac->tags_mapped++; return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1]; } case 3: case 2: - if (ac->tags_mapped == (ac->m4ac.chan_config != 2) && type == TYPE_CPE) { + if (ac->tags_mapped == (ac->oc[1].m4ac.chan_config != 2) && type == TYPE_CPE) { ac->tags_mapped++; return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][0]; - } else if (ac->m4ac.chan_config == 2) { + } else if (ac->oc[1].m4ac.chan_config == 2) { return NULL; } case 1: @@ -783,10 +827,10 @@ static av_cold int aac_decode_init(AVCodecContext *avctx) float output_scale_factor; ac->avctx = avctx; - ac->m4ac.sample_rate = avctx->sample_rate; + ac->oc[1].m4ac.sample_rate = avctx->sample_rate; if (avctx->extradata_size > 0) { - if (decode_audio_specific_config(ac, ac->avctx, &ac->m4ac, + if (decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac, avctx->extradata, avctx->extradata_size*8, 1) < 0) return -1; @@ -796,10 +840,10 @@ static av_cold int aac_decode_init(AVCodecContext *avctx) int layout_map_tags; sr = sample_rate_idx(avctx->sample_rate); - ac->m4ac.sampling_index = sr; - ac->m4ac.channels = avctx->channels; - ac->m4ac.sbr = -1; - ac->m4ac.ps = -1; + ac->oc[1].m4ac.sampling_index = sr; + ac->oc[1].m4ac.channels = avctx->channels; + ac->oc[1].m4ac.sbr = -1; + ac->oc[1].m4ac.ps = -1; for (i = 0; i < FF_ARRAY_ELEMS(ff_mpeg4audio_channels); i++) if (ff_mpeg4audio_channels[i] == avctx->channels) @@ -807,14 +851,14 @@ static av_cold int aac_decode_init(AVCodecContext *avctx) if (i == FF_ARRAY_ELEMS(ff_mpeg4audio_channels)) { i = 0; } - ac->m4ac.chan_config = i; + ac->oc[1].m4ac.chan_config = i; - if (ac->m4ac.chan_config) { + if (ac->oc[1].m4ac.chan_config) { int ret = set_default_channel_config(avctx, layout_map, - &layout_map_tags, ac->m4ac.chan_config); + &layout_map_tags, ac->oc[1].m4ac.chan_config); if (!ret) output_configure(ac, layout_map, layout_map_tags, - ac->m4ac.chan_config, OC_GLOBAL_HDR); + ac->oc[1].m4ac.chan_config, OC_GLOBAL_HDR); else if (avctx->err_recognition & AV_EF_EXPLODE) return AVERROR_INVALIDDATA; } @@ -902,7 +946,7 @@ static int decode_prediction(AACContext *ac, IndividualChannelStream *ics, return -1; } } - for (sfb = 0; sfb < FFMIN(ics->max_sfb, ff_aac_pred_sfb_max[ac->m4ac.sampling_index]); sfb++) { + for (sfb = 0; sfb < FFMIN(ics->max_sfb, ff_aac_pred_sfb_max[ac->oc[1].m4ac.sampling_index]); sfb++) { ics->prediction_used[sfb] = get_bits1(gb); } return 0; @@ -950,24 +994,24 @@ static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics, } } ics->num_windows = 8; - ics->swb_offset = ff_swb_offset_128[ac->m4ac.sampling_index]; - ics->num_swb = ff_aac_num_swb_128[ac->m4ac.sampling_index]; - ics->tns_max_bands = ff_tns_max_bands_128[ac->m4ac.sampling_index]; + ics->swb_offset = ff_swb_offset_128[ac->oc[1].m4ac.sampling_index]; + ics->num_swb = ff_aac_num_swb_128[ac->oc[1].m4ac.sampling_index]; + ics->tns_max_bands = ff_tns_max_bands_128[ac->oc[1].m4ac.sampling_index]; ics->predictor_present = 0; } else { ics->max_sfb = get_bits(gb, 6); ics->num_windows = 1; - ics->swb_offset = ff_swb_offset_1024[ac->m4ac.sampling_index]; - ics->num_swb = ff_aac_num_swb_1024[ac->m4ac.sampling_index]; - ics->tns_max_bands = ff_tns_max_bands_1024[ac->m4ac.sampling_index]; + ics->swb_offset = ff_swb_offset_1024[ac->oc[1].m4ac.sampling_index]; + ics->num_swb = ff_aac_num_swb_1024[ac->oc[1].m4ac.sampling_index]; + ics->tns_max_bands = ff_tns_max_bands_1024[ac->oc[1].m4ac.sampling_index]; ics->predictor_present = get_bits1(gb); ics->predictor_reset_group = 0; if (ics->predictor_present) { - if (ac->m4ac.object_type == AOT_AAC_MAIN) { + if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN) { if (decode_prediction(ac, ics, gb)) { goto fail; } - } else if (ac->m4ac.object_type == AOT_AAC_LC) { + } else if (ac->oc[1].m4ac.object_type == AOT_AAC_LC) { av_log(ac->avctx, AV_LOG_ERROR, "Prediction is not allowed in AAC-LC.\n"); goto fail; } else { @@ -1141,7 +1185,7 @@ static int decode_tns(AACContext *ac, TemporalNoiseShaping *tns, { int w, filt, i, coef_len, coef_res, coef_compress; const int is8 = ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE; - const int tns_max_order = is8 ? 7 : ac->m4ac.object_type == AOT_AAC_MAIN ? 20 : 12; + const int tns_max_order = is8 ? 7 : ac->oc[1].m4ac.object_type == AOT_AAC_MAIN ? 20 : 12; for (w = 0; w < ics->num_windows; w++) { if ((tns->n_filt[w] = get_bits(gb, 2 - is8))) { coef_res = get_bits1(gb); @@ -1552,7 +1596,7 @@ static void apply_prediction(AACContext *ac, SingleChannelElement *sce) } if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) { - for (sfb = 0; sfb < ff_aac_pred_sfb_max[ac->m4ac.sampling_index]; sfb++) { + for (sfb = 0; sfb < ff_aac_pred_sfb_max[ac->oc[1].m4ac.sampling_index]; sfb++) { for (k = sce->ics.swb_offset[sfb]; k < sce->ics.swb_offset[sfb + 1]; k++) { predict(&sce->predictor_state[k], &sce->coeffs[k], sce->ics.predictor_present && sce->ics.prediction_used[sfb]); @@ -1621,7 +1665,7 @@ static int decode_ics(AACContext *ac, SingleChannelElement *sce, if (decode_spectrum_and_dequant(ac, out, gb, sce->sf, pulse_present, &pulse, ics, sce->band_type) < 0) return -1; - if (ac->m4ac.object_type == AOT_AAC_MAIN && !common_window) + if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN && !common_window) apply_prediction(ac, sce); return 0; @@ -1711,7 +1755,7 @@ static int decode_cpe(AACContext *ac, GetBitContext *gb, ChannelElement *cpe) i = cpe->ch[1].ics.use_kb_window[0]; cpe->ch[1].ics = cpe->ch[0].ics; cpe->ch[1].ics.use_kb_window[1] = i; - if (cpe->ch[1].ics.predictor_present && (ac->m4ac.object_type != AOT_AAC_MAIN)) + if (cpe->ch[1].ics.predictor_present && (ac->oc[1].m4ac.object_type != AOT_AAC_MAIN)) if ((cpe->ch[1].ics.ltp.present = get_bits(gb, 1))) decode_ltp(ac, &cpe->ch[1].ics.ltp, gb, cpe->ch[1].ics.max_sfb); ms_present = get_bits(gb, 2); @@ -1729,7 +1773,7 @@ static int decode_cpe(AACContext *ac, GetBitContext *gb, ChannelElement *cpe) if (common_window) { if (ms_present) apply_mid_side_stereo(ac, cpe); - if (ac->m4ac.object_type == AOT_AAC_MAIN) { + if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN) { apply_prediction(ac, &cpe->ch[0]); apply_prediction(ac, &cpe->ch[1]); } @@ -1910,21 +1954,21 @@ static int decode_extension_payload(AACContext *ac, GetBitContext *gb, int cnt, if (!che) { av_log(ac->avctx, AV_LOG_ERROR, "SBR was found before the first channel element.\n"); return res; - } else if (!ac->m4ac.sbr) { + } else if (!ac->oc[1].m4ac.sbr) { av_log(ac->avctx, AV_LOG_ERROR, "SBR signaled to be not-present but was found in the bitstream.\n"); skip_bits_long(gb, 8 * cnt - 4); return res; - } else if (ac->m4ac.sbr == -1 && ac->output_configured == OC_LOCKED) { + } else if (ac->oc[1].m4ac.sbr == -1 && ac->oc[1].status == OC_LOCKED) { av_log(ac->avctx, AV_LOG_ERROR, "Implicit SBR was found with a first occurrence after the first frame.\n"); skip_bits_long(gb, 8 * cnt - 4); return res; - } else if (ac->m4ac.ps == -1 && ac->output_configured < OC_LOCKED && ac->avctx->channels == 1) { - ac->m4ac.sbr = 1; - ac->m4ac.ps = 1; - output_configure(ac, ac->layout_map, ac->layout_map_tags, - ac->m4ac.chan_config, ac->output_configured); + } else if (ac->oc[1].m4ac.ps == -1 && ac->oc[1].status < OC_LOCKED && ac->avctx->channels == 1) { + ac->oc[1].m4ac.sbr = 1; + ac->oc[1].m4ac.ps = 1; + output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags, + ac->oc[1].m4ac.chan_config, ac->oc[1].status); } else { - ac->m4ac.sbr = 1; + ac->oc[1].m4ac.sbr = 1; } res = ff_decode_sbr_extension(ac, &che->sbr, gb, crc_flag, cnt, elem_type); break; @@ -2170,7 +2214,7 @@ static void apply_dependent_coupling(AACContext *ac, float *dest = target->coeffs; const float *src = cce->ch[0].coeffs; int g, i, group, k, idx = 0; - if (ac->m4ac.object_type == AOT_AAC_LTP) { + if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) { av_log(ac->avctx, AV_LOG_ERROR, "Dependent coupling is not supported together with LTP\n"); return; @@ -2205,7 +2249,7 @@ static void apply_independent_coupling(AACContext *ac, const float gain = cce->coup.gain[index][0]; const float *src = cce->ch[0].ret; float *dest = target->ret; - const int len = 1024 << (ac->m4ac.sbr == 1); + const int len = 1024 << (ac->oc[1].m4ac.sbr == 1); for (i = 0; i < len; i++) dest[i] += gain * src[i]; @@ -2258,7 +2302,7 @@ static void spectral_to_sample(AACContext *ac) if (che) { if (type <= TYPE_CPE) apply_channel_coupling(ac, che, type, i, BEFORE_TNS, apply_dependent_coupling); - if (ac->m4ac.object_type == AOT_AAC_LTP) { + if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) { if (che->ch[0].ics.predictor_present) { if (che->ch[0].ics.ltp.present) apply_ltp(ac, &che->ch[0]); @@ -2274,14 +2318,14 @@ static void spectral_to_sample(AACContext *ac) apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, apply_dependent_coupling); if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) { imdct_and_windowing(ac, &che->ch[0]); - if (ac->m4ac.object_type == AOT_AAC_LTP) + if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) update_ltp(ac, &che->ch[0]); if (type == TYPE_CPE) { imdct_and_windowing(ac, &che->ch[1]); - if (ac->m4ac.object_type == AOT_AAC_LTP) + if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) update_ltp(ac, &che->ch[1]); } - if (ac->m4ac.sbr > 0) { + if (ac->oc[1].m4ac.sbr > 0) { ff_sbr_apply(ac, &che->sbr, type, che->ch[0].ret, che->ch[1].ret); } } @@ -2301,33 +2345,33 @@ static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb) size = avpriv_aac_parse_header(gb, &hdr_info); if (size > 0) { + if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) { + // This is 2 for "VLB " audio in NSV files. + // See samples/nsv/vlb_audio. + av_log_missing_feature(ac->avctx, "More than one AAC RDB per ADTS frame is", 0); + ac->warned_num_aac_frames = 1; + } + push_output_configuration(ac); if (hdr_info.chan_config) { - ac->m4ac.chan_config = hdr_info.chan_config; + ac->oc[1].m4ac.chan_config = hdr_info.chan_config; if (set_default_channel_config(ac->avctx, layout_map, &layout_map_tags, hdr_info.chan_config)) return -7; if (output_configure(ac, layout_map, layout_map_tags, hdr_info.chan_config, - FFMAX(ac->output_configured, OC_TRIAL_FRAME))) + FFMAX(ac->oc[1].status, OC_TRIAL_FRAME))) return -7; - } else if (ac->output_configured != OC_LOCKED) { - ac->m4ac.chan_config = 0; - ac->output_configured = OC_NONE; - } - if (ac->output_configured != OC_LOCKED) { - ac->m4ac.sbr = -1; - ac->m4ac.ps = -1; - ac->m4ac.sample_rate = hdr_info.sample_rate; - ac->m4ac.sampling_index = hdr_info.sampling_index; - ac->m4ac.object_type = hdr_info.object_type; + } else { + ac->oc[1].m4ac.chan_config = 0; } - if (!ac->avctx->sample_rate) - ac->avctx->sample_rate = hdr_info.sample_rate; - if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) { - // This is 2 for "VLB " audio in NSV files. - // See samples/nsv/vlb_audio. - av_log_missing_feature(ac->avctx, "More than one AAC RDB per ADTS frame is", 0); - ac->warned_num_aac_frames = 1; + ac->oc[1].m4ac.sample_rate = hdr_info.sample_rate; + ac->oc[1].m4ac.sampling_index = hdr_info.sampling_index; + ac->oc[1].m4ac.object_type = hdr_info.object_type; + if (ac->oc[0].status != OC_LOCKED || + ac->oc[0].m4ac.chan_config != hdr_info.chan_config || + ac->oc[0].m4ac.sample_rate != hdr_info.sample_rate) { + ac->oc[1].m4ac.sbr = -1; + ac->oc[1].m4ac.ps = -1; } if (!hdr_info.crc_absent) skip_bits(gb, 16); @@ -2342,16 +2386,18 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, ChannelElement *che = NULL, *che_prev = NULL; enum RawDataBlockType elem_type, elem_type_prev = TYPE_END; int err, elem_id; - int samples = 0, multiplier, audio_found = 0; + int samples = 0, multiplier, audio_found = 0, pce_found = 0; if (show_bits(gb, 12) == 0xfff) { if (parse_adts_frame_header(ac, gb) < 0) { av_log(avctx, AV_LOG_ERROR, "Error decoding AAC frame header.\n"); - return -1; + err = -1; + goto fail; } - if (ac->m4ac.sampling_index > 12) { - av_log(ac->avctx, AV_LOG_ERROR, "invalid sampling rate index %d\n", ac->m4ac.sampling_index); - return -1; + if (ac->oc[1].m4ac.sampling_index > 12) { + av_log(ac->avctx, AV_LOG_ERROR, "invalid sampling rate index %d\n", ac->oc[1].m4ac.sampling_index); + err = -1; + goto fail; } } @@ -2364,7 +2410,8 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, if (!(che=get_che(ac, elem_type, elem_id))) { av_log(ac->avctx, AV_LOG_ERROR, "channel element %d.%d is not allocated\n", elem_type, elem_id); - return -1; + err = -1; + goto fail; } samples = 1024; } @@ -2397,17 +2444,20 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, case TYPE_PCE: { uint8_t layout_map[MAX_ELEM_ID*4][3]; int tags; - tags = decode_pce(avctx, &ac->m4ac, layout_map, gb); + push_output_configuration(ac); + tags = decode_pce(avctx, &ac->oc[1].m4ac, layout_map, gb); if (tags < 0) { err = tags; break; } - if (ac->output_configured > OC_TRIAL_PCE) + if (pce_found) { av_log(avctx, AV_LOG_INFO, "Evaluating a further program_config_element.\n"); + } err = output_configure(ac, layout_map, tags, 0, OC_TRIAL_PCE); if (!err) - ac->m4ac.chan_config = 0; + ac->oc[1].m4ac.chan_config = 0; + pce_found = 1; break; } @@ -2416,7 +2466,8 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, elem_id += get_bits(gb, 8) - 1; if (get_bits_left(gb) < 8 * elem_id) { av_log(avctx, AV_LOG_ERROR, overread_err); - return -1; + err = -1; + goto fail; } while (elem_id > 0) elem_id -= decode_extension_payload(ac, gb, elem_id, che_prev, elem_type_prev); @@ -2432,29 +2483,27 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, elem_type_prev = elem_type; if (err) - return err; + goto fail; if (get_bits_left(gb) < 3) { av_log(avctx, AV_LOG_ERROR, overread_err); - return -1; + err = -1; + goto fail; } } spectral_to_sample(ac); - multiplier = (ac->m4ac.sbr == 1) ? ac->m4ac.ext_sample_rate > ac->m4ac.sample_rate : 0; + multiplier = (ac->oc[1].m4ac.sbr == 1) ? ac->oc[1].m4ac.ext_sample_rate > ac->oc[1].m4ac.sample_rate : 0; samples <<= multiplier; - if (ac->output_configured < OC_LOCKED) { - avctx->sample_rate = ac->m4ac.sample_rate << multiplier; - avctx->frame_size = samples; - } if (samples) { /* get output buffer */ ac->frame.nb_samples = samples; if ((err = avctx->get_buffer(avctx, &ac->frame)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); - return err; + err = -1; + goto fail; } if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT) @@ -2470,10 +2519,16 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, } *got_frame_ptr = !!samples; - if (ac->output_configured && audio_found) - ac->output_configured = OC_LOCKED; + if (ac->oc[1].status && audio_found) { + avctx->sample_rate = ac->oc[1].m4ac.sample_rate << multiplier; + avctx->frame_size = samples; + ac->oc[1].status = OC_LOCKED; + } return 0; +fail: + pop_output_configuration(ac); + return err; } static int aac_decode_frame(AVCodecContext *avctx, void *data, @@ -2499,10 +2554,13 @@ static int aac_decode_frame(AVCodecContext *avctx, void *data, return AVERROR(ENOMEM); avctx->extradata_size = new_extradata_size; memcpy(avctx->extradata, new_extradata, new_extradata_size); - if (decode_audio_specific_config(ac, ac->avctx, &ac->m4ac, + push_output_configuration(ac); + if (decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac, avctx->extradata, - avctx->extradata_size*8, 1) < 0) + avctx->extradata_size*8, 1) < 0) { + pop_output_configuration(ac); return AVERROR_INVALIDDATA; + } } init_get_bits(&gb, buf, buf_size * 8); @@ -2562,7 +2620,7 @@ static int latm_decode_audio_specific_config(struct LATMContext *latmctx, { AACContext *ac = &latmctx->aac_ctx; AVCodecContext *avctx = ac->avctx; - MPEG4AudioConfig m4ac = {0}; + MPEG4AudioConfig m4ac = { 0 }; int config_start_bit = get_bits_count(gb); int sync_extension = 0; int bits_consumed, esize; @@ -2587,8 +2645,8 @@ static int latm_decode_audio_specific_config(struct LATMContext *latmctx, if (bits_consumed < 0) return AVERROR_INVALIDDATA; - if (ac->m4ac.sample_rate != m4ac.sample_rate || - ac->m4ac.chan_config != m4ac.chan_config) { + if (ac->oc[1].m4ac.sample_rate != m4ac.sample_rate || + ac->oc[1].m4ac.chan_config != m4ac.chan_config) { av_log(avctx, AV_LOG_INFO, "audio config changed\n"); latmctx->initialized = 0; @@ -2769,10 +2827,13 @@ static int latm_decode_frame(AVCodecContext *avctx, void *out, *got_frame_ptr = 0; return avpkt->size; } else { + push_output_configuration(&latmctx->aac_ctx); if ((err = decode_audio_specific_config( - &latmctx->aac_ctx, avctx, &latmctx->aac_ctx.m4ac, - avctx->extradata, avctx->extradata_size*8, 1)) < 0) + &latmctx->aac_ctx, avctx, &latmctx->aac_ctx.oc[1].m4ac, + avctx->extradata, avctx->extradata_size*8, 1)) < 0) { + pop_output_configuration(&latmctx->aac_ctx); return err; + } latmctx->initialized = 1; } } diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index 3460d51218..234ebff39a 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -571,8 +571,10 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } start_ch += chans; } - if ((ret = ff_alloc_packet2(avctx, avpkt, 768 * s->channels))) + if ((ret = ff_alloc_packet2(avctx, avpkt, 768 * s->channels))) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n"); return ret; + } do { int frame_bits; diff --git a/libavcodec/aacsbr.c b/libavcodec/aacsbr.c index ea2dcbb69b..40ee8f5127 100644 --- a/libavcodec/aacsbr.c +++ b/libavcodec/aacsbr.c @@ -918,7 +918,7 @@ static void read_sbr_extension(AACContext *ac, SpectralBandReplication *sbr, { switch (bs_extension_id) { case EXTENSION_ID_PS: - if (!ac->m4ac.ps) { + if (!ac->oc[1].m4ac.ps) { av_log(ac->avctx, AV_LOG_ERROR, "Parametric Stereo signaled to be not-present but was found in the bitstream.\n"); skip_bits_long(gb, *num_bits_left); // bs_fill_bits *num_bits_left = 0; @@ -1077,9 +1077,9 @@ int ff_decode_sbr_extension(AACContext *ac, SpectralBandReplication *sbr, sbr->reset = 0; if (!sbr->sample_rate) - sbr->sample_rate = 2 * ac->m4ac.sample_rate; //TODO use the nominal sample rate for arbitrary sample rate support - if (!ac->m4ac.ext_sample_rate) - ac->m4ac.ext_sample_rate = 2 * ac->m4ac.sample_rate; + sbr->sample_rate = 2 * ac->oc[1].m4ac.sample_rate; //TODO use the nominal sample rate for arbitrary sample rate support + if (!ac->oc[1].m4ac.ext_sample_rate) + ac->oc[1].m4ac.ext_sample_rate = 2 * ac->oc[1].m4ac.sample_rate; if (crc) { skip_bits(gb, 10); // bs_sbr_crc_bits; TODO - implement CRC check @@ -1654,7 +1654,7 @@ static void sbr_hf_assemble(float Y1[38][64][2], void ff_sbr_apply(AACContext *ac, SpectralBandReplication *sbr, int id_aac, float* L, float* R) { - int downsampled = ac->m4ac.ext_sample_rate < sbr->sample_rate; + int downsampled = ac->oc[1].m4ac.ext_sample_rate < sbr->sample_rate; int ch; int nch = (id_aac == TYPE_CPE) ? 2 : 1; int err; @@ -1701,7 +1701,7 @@ void ff_sbr_apply(AACContext *ac, SpectralBandReplication *sbr, int id_aac, sbr->X_low, ch); } - if (ac->m4ac.ps == 1) { + if (ac->oc[1].m4ac.ps == 1) { if (sbr->ps.start) { ff_ps_apply(ac->avctx, &sbr->ps, sbr->X[0], sbr->X[1], sbr->kx[1] + sbr->m[1]); } else { diff --git a/libavcodec/dv_tablegen.h b/libavcodec/dv_tablegen.h index 9b3e406f6a..e8cdc21dcf 100644 --- a/libavcodec/dv_tablegen.h +++ b/libavcodec/dv_tablegen.h @@ -25,7 +25,6 @@ #include <stdint.h> -#include "libavutil/attributes.h" #include "dv_vlc_data.h" #if CONFIG_SMALL @@ -48,7 +47,7 @@ typedef struct dv_vlc_pair { #else static struct dv_vlc_pair dv_vlc_map[DV_VLC_MAP_RUN_SIZE][DV_VLC_MAP_LEV_SIZE]; -static void av_unused dv_vlc_map_tableinit(void) +static void dv_vlc_map_tableinit(void) { int i, j; for (i = 0; i < NB_DV_VLC - 1; i++) { diff --git a/libavcodec/libfaac.c b/libavcodec/libfaac.c index 8169b0a16b..c174f7af36 100644 --- a/libavcodec/libfaac.c +++ b/libavcodec/libfaac.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "audio_frame_queue.h" #include "internal.h" +#include "libavutil/audioconvert.h" /* libfaac has an encoder delay of 1024 samples */ @@ -39,13 +40,6 @@ typedef struct FaacAudioContext { AudioFrameQueue afq; } FaacAudioContext; -static const int channel_maps[][6] = { - { 2, 0, 1 }, //< C L R - { 2, 0, 1, 3 }, //< C L R Cs - { 2, 0, 1, 3, 4 }, //< C L R Ls Rs - { 2, 0, 1, 4, 5, 3 }, //< C L R Ls Rs LFE -}; - static av_cold int Faac_encode_close(AVCodecContext *avctx) { FaacAudioContext *s = avctx->priv_data; @@ -62,6 +56,13 @@ static av_cold int Faac_encode_close(AVCodecContext *avctx) return 0; } +static const int channel_maps[][6] = { + { 2, 0, 1 }, //< C L R + { 2, 0, 1, 3 }, //< C L R Cs + { 2, 0, 1, 3, 4 }, //< C L R Ls Rs + { 2, 0, 1, 4, 5, 3 }, //< C L R Ls Rs LFE +}; + static av_cold int Faac_encode_init(AVCodecContext *avctx) { FaacAudioContext *s = avctx->priv_data; @@ -184,8 +185,10 @@ static int Faac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, int num_samples = frame ? frame->nb_samples : 0; void *samples = frame ? frame->data[0] : NULL; - if ((ret = ff_alloc_packet2(avctx, avpkt, (7 + 768) * avctx->channels))) + if ((ret = ff_alloc_packet2(avctx, avpkt, (7 + 768) * avctx->channels))) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n"); return ret; + } bytes_written = faacEncEncode(s->faac_handle, samples, num_samples * avctx->channels, @@ -221,6 +224,16 @@ static const AVProfile profiles[] = { { FF_PROFILE_UNKNOWN }, }; +static const uint64_t faac_channel_layouts[] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_5POINT1_BACK, + 0 +}; + AVCodec ff_libfaac_encoder = { .name = "libfaac", .type = AVMEDIA_TYPE_AUDIO, @@ -234,4 +247,5 @@ AVCodec ff_libfaac_encoder = { AV_SAMPLE_FMT_NONE }, .long_name = NULL_IF_CONFIG_SMALL("libfaac AAC (Advanced Audio Codec)"), .profiles = NULL_IF_CONFIG_SMALL(profiles), + .channel_layouts = faac_channel_layouts, }; diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c index eb962b7a98..b5339c6ce1 100644 --- a/libavcodec/proresenc_kostya.c +++ b/libavcodec/proresenc_kostya.c @@ -169,6 +169,13 @@ struct TrellisNode { #define MAX_STORED_Q 16 +typedef struct ProresThreadData { + DECLARE_ALIGNED(16, DCTELEM, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE]; + DECLARE_ALIGNED(16, uint16_t, emu_buf)[16 * 16]; + int16_t custom_q[64]; + struct TrellisNode *nodes; +} ProresThreadData; + typedef struct ProresContext { AVClass *class; DECLARE_ALIGNED(16, DCTELEM, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE]; @@ -197,13 +204,14 @@ typedef struct ProresContext { int profile; const struct prores_profile *profile_info; - struct TrellisNode *nodes; int *slice_q; + + ProresThreadData *tdata; } ProresContext; static void get_slice_data(ProresContext *ctx, const uint16_t *src, int linesize, int x, int y, int w, int h, - DCTELEM *blocks, + DCTELEM *blocks, uint16_t *emu_buf, int mbs_per_slice, int blocks_per_mb, int is_chroma) { const uint16_t *esrc; @@ -223,24 +231,24 @@ static void get_slice_data(ProresContext *ctx, const uint16_t *src, } else { int bw, bh, pix; - esrc = ctx->emu_buf; - elinesize = 16 * sizeof(*ctx->emu_buf); + esrc = emu_buf; + elinesize = 16 * sizeof(*emu_buf); bw = FFMIN(w - x, mb_width); bh = FFMIN(h - y, 16); for (j = 0; j < bh; j++) { - memcpy(ctx->emu_buf + j * 16, + memcpy(emu_buf + j * 16, (const uint8_t*)src + j * linesize, bw * sizeof(*src)); - pix = ctx->emu_buf[j * 16 + bw - 1]; + pix = emu_buf[j * 16 + bw - 1]; for (k = bw; k < mb_width; k++) - ctx->emu_buf[j * 16 + k] = pix; + emu_buf[j * 16 + k] = pix; } for (; j < 16; j++) - memcpy(ctx->emu_buf + j * 16, - ctx->emu_buf + (bh - 1) * 16, - mb_width * sizeof(*ctx->emu_buf)); + memcpy(emu_buf + j * 16, + emu_buf + (bh - 1) * 16, + mb_width * sizeof(*emu_buf)); } if (!is_chroma) { ctx->dsp.fdct(esrc, elinesize, blocks); @@ -429,7 +437,7 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, 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], + pwidth, avctx->height, ctx->blocks[0], ctx->emu_buf, mbs_per_slice, num_cblocks, is_chroma); sizes[i] = encode_slice_plane(ctx, pb, src, pic->linesize[i], mbs_per_slice, ctx->blocks[0], @@ -533,22 +541,23 @@ static int estimate_slice_plane(ProresContext *ctx, int *error, int plane, const uint16_t *src, int linesize, int mbs_per_slice, int blocks_per_mb, int plane_size_factor, - const int16_t *qmat) + const int16_t *qmat, ProresThreadData *td) { int blocks_per_slice; int bits; blocks_per_slice = mbs_per_slice * blocks_per_mb; - bits = estimate_dcs(error, ctx->blocks[plane], blocks_per_slice, qmat[0]); - bits += estimate_acs(error, ctx->blocks[plane], blocks_per_slice, + bits = estimate_dcs(error, td->blocks[plane], blocks_per_slice, qmat[0]); + bits += estimate_acs(error, td->blocks[plane], blocks_per_slice, plane_size_factor, ctx->scantable.permutated, qmat); return FFALIGN(bits, 8); } static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, - int trellis_node, int x, int y, int mbs_per_slice) + int trellis_node, int x, int y, int mbs_per_slice, + ProresThreadData *td) { ProresContext *ctx = avctx->priv_data; int i, q, pq, xp, yp; @@ -585,13 +594,13 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, 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[i], + pwidth, avctx->height, td->blocks[i], td->emu_buf, mbs_per_slice, num_cblocks[i], is_chroma[i]); } for (q = min_quant; q < max_quant + 2; q++) { - ctx->nodes[trellis_node + q].prev_node = -1; - ctx->nodes[trellis_node + q].quant = q; + td->nodes[trellis_node + q].prev_node = -1; + td->nodes[trellis_node + q].quant = q; } // todo: maybe perform coarser quantising to fit into frame size when needed @@ -603,7 +612,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, src, pic->linesize[i], mbs_per_slice, num_cblocks[i], plane_factor[i], - ctx->quants[q]); + ctx->quants[q], td); } if (bits > 65000 * 8) { error = SCORE_LIMIT; @@ -623,7 +632,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, if (q < MAX_STORED_Q) { qmat = ctx->quants[q]; } else { - qmat = ctx->custom_q; + qmat = td->custom_q; for (i = 0; i < 64; i++) qmat[i] = ctx->quant_mat[i] * q; } @@ -632,7 +641,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, src, pic->linesize[i], mbs_per_slice, num_cblocks[i], plane_factor[i], - qmat); + qmat, td); } if (bits <= ctx->bits_per_mb * mbs_per_slice) break; @@ -642,7 +651,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, slice_score[max_quant + 1] = error; overquant = q; } - ctx->nodes[trellis_node + max_quant + 1].quant = overquant; + td->nodes[trellis_node + max_quant + 1].quant = overquant; bits_limit = mbs * ctx->bits_per_mb; for (pq = min_quant; pq < max_quant + 2; pq++) { @@ -651,30 +660,30 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, for (q = min_quant; q < max_quant + 2; q++) { cur = trellis_node + q; - bits = ctx->nodes[prev].bits + slice_bits[q]; + bits = td->nodes[prev].bits + slice_bits[q]; error = slice_score[q]; if (bits > bits_limit) error = SCORE_LIMIT; - if (ctx->nodes[prev].score < SCORE_LIMIT && error < SCORE_LIMIT) - new_score = ctx->nodes[prev].score + error; + if (td->nodes[prev].score < SCORE_LIMIT && error < SCORE_LIMIT) + new_score = td->nodes[prev].score + error; else new_score = SCORE_LIMIT; - if (ctx->nodes[cur].prev_node == -1 || - ctx->nodes[cur].score >= new_score) { + if (td->nodes[cur].prev_node == -1 || + td->nodes[cur].score >= new_score) { - ctx->nodes[cur].bits = bits; - ctx->nodes[cur].score = new_score; - ctx->nodes[cur].prev_node = prev; + td->nodes[cur].bits = bits; + td->nodes[cur].score = new_score; + td->nodes[cur].prev_node = prev; } } } - error = ctx->nodes[trellis_node + min_quant].score; + error = td->nodes[trellis_node + min_quant].score; pq = trellis_node + min_quant; for (q = min_quant + 1; q < max_quant + 2; q++) { - if (ctx->nodes[trellis_node + q].score <= error) { - error = ctx->nodes[trellis_node + q].score; + if (td->nodes[trellis_node + q].score <= error) { + error = td->nodes[trellis_node + q].score; pq = trellis_node + q; } } @@ -682,6 +691,30 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, return pq; } +static int find_quant_thread(AVCodecContext *avctx, void *arg, + int jobnr, int threadnr) +{ + ProresContext *ctx = avctx->priv_data; + ProresThreadData *td = ctx->tdata + threadnr; + int mbs_per_slice = ctx->mbs_per_slice; + int x, y = jobnr, mb, q = 0; + + for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) { + while (ctx->mb_width - x < mbs_per_slice) + mbs_per_slice >>= 1; + q = find_slice_quant(avctx, avctx->coded_frame, + (mb + 1) * TRELLIS_WIDTH, x, y, + mbs_per_slice, td); + } + + for (x = ctx->slices_width - 1; x >= 0; x--) { + ctx->slice_q[x + y * ctx->slices_width] = td->nodes[q].quant; + q = td->nodes[q].prev_node; + } + + return 0; +} + static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pic, int *got_packet) { @@ -751,25 +784,18 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, buf += ctx->num_slices * 2; // slices - for (y = 0; y < ctx->mb_height; y++) { - mbs_per_slice = ctx->mbs_per_slice; - if (!ctx->force_quant) { - for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) { - while (ctx->mb_width - x < mbs_per_slice) - mbs_per_slice >>= 1; - q = find_slice_quant(avctx, pic, (mb + 1) * TRELLIS_WIDTH, x, y, - mbs_per_slice); - } - - for (x = ctx->slices_width - 1; x >= 0; x--) { - ctx->slice_q[x] = ctx->nodes[q].quant; - q = ctx->nodes[q].prev_node; - } - } + 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++) { 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]; + 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; @@ -807,13 +833,18 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, static av_cold int encode_close(AVCodecContext *avctx) { ProresContext *ctx = avctx->priv_data; + int i; if (avctx->coded_frame->data[0]) avctx->release_buffer(avctx, avctx->coded_frame); av_freep(&avctx->coded_frame); - av_freep(&ctx->nodes); + if (ctx->tdata) { + for (i = 0; i < avctx->thread_count; i++) + av_free(ctx->tdata[i].nodes); + } + av_freep(&ctx->tdata); av_freep(&ctx->slice_q); return 0; @@ -883,23 +914,32 @@ static av_cold int encode_init(AVCodecContext *avctx) ctx->quants[i][j] = ctx->quant_mat[j] * i; } - ctx->nodes = av_malloc((ctx->slices_width + 1) * TRELLIS_WIDTH - * sizeof(*ctx->nodes)); - if (!ctx->nodes) { + ctx->slice_q = av_malloc(ctx->num_slices * sizeof(*ctx->slice_q)); + if (!ctx->slice_q) { encode_close(avctx); return AVERROR(ENOMEM); } - for (i = min_quant; i < max_quant + 2; i++) { - ctx->nodes[i].prev_node = -1; - ctx->nodes[i].bits = 0; - ctx->nodes[i].score = 0; - } - ctx->slice_q = av_malloc(ctx->slices_width * sizeof(*ctx->slice_q)); - if (!ctx->slice_q) { + ctx->tdata = av_mallocz(avctx->thread_count * sizeof(*ctx->tdata)); + if (!ctx->tdata) { encode_close(avctx); return AVERROR(ENOMEM); } + + for (j = 0; j < avctx->thread_count; j++) { + ctx->tdata[j].nodes = av_malloc((ctx->slices_width + 1) + * TRELLIS_WIDTH + * sizeof(*ctx->tdata->nodes)); + if (!ctx->tdata[j].nodes) { + encode_close(avctx); + return AVERROR(ENOMEM); + } + for (i = min_quant; i < max_quant + 2; i++) { + ctx->tdata[j].nodes[i].prev_node = -1; + ctx->tdata[j].nodes[i].bits = 0; + ctx->tdata[j].nodes[i].score = 0; + } + } } else { int ls = 0; @@ -987,6 +1027,7 @@ AVCodec ff_prores_kostya_encoder = { .init = encode_init, .close = encode_close, .encode2 = encode_frame, + .capabilities = CODEC_CAP_SLICE_THREADS, .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"), .pix_fmts = (const enum PixelFormat[]) { PIX_FMT_YUV422P10, PIX_FMT_YUV444P10, PIX_FMT_NONE diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 7a47ad2e68..521e9b8c6a 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -28,6 +28,7 @@ #include "libavutil/avstring.h" #include "libavutil/intfloat.h" #include "libavutil/lfg.h" +#include "libavutil/opt.h" #include "libavutil/sha.h" #include "avformat.h" #include "internal.h" @@ -41,6 +42,9 @@ //#define DEBUG +#define APP_MAX_LENGTH 128 +#define PLAYPATH_MAX_LENGTH 256 + /** RTMP protocol handler state */ typedef enum { STATE_START, ///< client has not done anything yet @@ -56,12 +60,13 @@ typedef enum { /** protocol handler context */ typedef struct RTMPContext { + const AVClass *class; URLContext* stream; ///< TCP stream used in interactions with RTMP server RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets int chunk_size; ///< size of the chunks RTMP packets are divided into int is_input; ///< input/output flag - char playpath[256]; ///< path to filename to play (with possible "mp4:" prefix) - char app[128]; ///< application + char *playpath; ///< stream identifier to play (with possible "mp4:" prefix) + char *app; ///< name of application ClientState state; ///< current state int main_channel_id; ///< an additional channel ID which is used for some invocations uint8_t* flv_data; ///< buffer with data for demuxer @@ -822,6 +827,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) { RTMPContext *rt = s->priv_data; char proto[8], hostname[256], path[1024], *fname; + char *old_app; uint8_t buf[2048]; int port; int ret; @@ -847,6 +853,16 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) rt->chunk_size = 128; rt->state = STATE_HANDSHAKED; + + // Keep the application name when it has been defined by the user. + old_app = rt->app; + + rt->app = av_malloc(APP_MAX_LENGTH); + if (!rt->app) { + rtmp_close(s); + return AVERROR(ENOMEM); + } + //extract "app" part from path if (!strncmp(path, "/ondemand/", 10)) { fname = path + 10; @@ -868,14 +884,29 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) } } } - if (!strchr(fname, ':') && - (!strcmp(fname + strlen(fname) - 4, ".f4v") || - !strcmp(fname + strlen(fname) - 4, ".mp4"))) { - memcpy(rt->playpath, "mp4:", 5); - } else { - rt->playpath[0] = 0; + + if (old_app) { + // The name of application has been defined by the user, override it. + av_free(rt->app); + rt->app = old_app; + } + + if (!rt->playpath) { + rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH); + if (!rt->playpath) { + rtmp_close(s); + return AVERROR(ENOMEM); + } + + if (!strchr(fname, ':') && + (!strcmp(fname + strlen(fname) - 4, ".f4v") || + !strcmp(fname + strlen(fname) - 4, ".mp4"))) { + memcpy(rt->playpath, "mp4:", 5); + } else { + rt->playpath[0] = 0; + } + strncat(rt->playpath, fname, PLAYPATH_MAX_LENGTH - 5); } - strncat(rt->playpath, fname, sizeof(rt->playpath) - 5); rt->client_report_size = 1048576; rt->bytes_read = 0; @@ -1013,6 +1044,23 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size) return size; } +#define OFFSET(x) offsetof(RTMPContext, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +#define ENC AV_OPT_FLAG_ENCODING_PARAM + +static const AVOption rtmp_options[] = { + {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, + {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, + { NULL }, +}; + +static const AVClass rtmp_class = { + .class_name = "rtmp", + .item_name = av_default_item_name, + .option = rtmp_options, + .version = LIBAVUTIL_VERSION_INT, +}; + URLProtocol ff_rtmp_protocol = { .name = "rtmp", .url_open = rtmp_open, @@ -1021,4 +1069,5 @@ URLProtocol ff_rtmp_protocol = { .url_close = rtmp_close, .priv_data_size = sizeof(RTMPContext), .flags = URL_PROTOCOL_FLAG_NETWORK, + .priv_data_class= &rtmp_class, }; diff --git a/libavutil/samplefmt.h b/libavutil/samplefmt.h index af015d0cc3..99fde99e8c 100644 --- a/libavutil/samplefmt.h +++ b/libavutil/samplefmt.h @@ -22,7 +22,26 @@ #include "avutil.h" /** - * all in native-endian format + * Audio Sample Formats + * + * @par + * The data described by the sample format is always in native-endian order. + * Sample values can be expressed by native C types, hence the lack of a signed + * 24-bit sample format even though it is a common raw audio data format. + * + * @par + * The floating-point formats are based on full volume being in the range + * [-1.0, 1.0]. Any values outside this range are beyond full volume level. + * + * @par + * The data layout as used in av_samples_fill_arrays() and elsewhere in Libav + * (such as AVFrame in libavcodec) is as follows: + * + * For planar sample formats, each audio channel is in a separate data plane, + * and linesize is the buffer size, in bytes, for a single plane. All data + * planes must be the same size. For packed sample formats, only the first data + * plane is used, and samples for each channel are interleaved. In this case, + * linesize is the buffer size, in bytes, for the 1 plane. */ enum AVSampleFormat { AV_SAMPLE_FMT_NONE = -1, @@ -147,6 +166,9 @@ int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, * buffer for planar layout, or the aligned size of the buffer for all channels * for packed layout. * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * * @param[out] audio_data array to be filled with the pointer for each channel * @param[out] linesize calculated linesize, may be NULL * @param buf the pointer to a buffer containing the samples @@ -165,6 +187,9 @@ int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, uint8_t *buf, * linesize accordingly. * The allocated samples buffer can be freed by using av_freep(&audio_data[0]) * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * * @param[out] audio_data array to be filled with the pointer for each channel * @param[out] linesize aligned size for audio buffer(s), may be NULL * @param nb_channels number of audio channels |