vod_status_t adts_encoder_init( adts_encoder_state_t* state, request_context_t* request_context, hls_encryption_params_t* encryption_params, const media_filter_t* next_filter, void* next_filter_context, const u_char* extra_data, uint32_t extra_data_size) { mp4a_config_t codec_config; vod_status_t rc; state->next_filter = next_filter; state->next_filter_context = next_filter_context; if (request_context->simulation_only) { return VOD_OK; } if (encryption_params->type == HLS_ENC_SAMPLE_AES) { rc = sample_aes_aac_filter_init( &state->sample_aes_context, request_context, next_filter->write, next_filter_context, encryption_params->key, encryption_params->iv); if (rc != VOD_OK) { return rc; } state->body_write = sample_aes_aac_filter_write_frame_body; state->body_write_context = state->sample_aes_context; } else { state->sample_aes_context = NULL; state->body_write = next_filter->write; state->body_write_context = next_filter_context; } rc = codec_config_mp4a_config_parse(request_context, extra_data, extra_data_size, &codec_config); if (rc != VOD_OK) { return rc; } // Note: not parsing all the special cases handled in ffmpeg's avpriv_mpeg4audio_get_config // Note: not handling pce_data vod_log_debug3(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "adts_encoder_init: object_type=%d sample_rate_index=%d channel_config=%d", codec_config.object_type, codec_config.sample_rate_index, codec_config.channel_config); vod_memzero(&state->header, sizeof(state->header)); adts_frame_header_set_syncword(state->header, 0xfff); adts_frame_header_set_protection_absent(state->header, 1); adts_frame_header_set_profile_object_type(state->header, codec_config.object_type - 1); adts_frame_header_set_sample_rate_index(state->header, codec_config.sample_rate_index); adts_frame_header_set_channel_configuration(state->header, codec_config.channel_config); adts_frame_header_set_adts_buffer_fullness(state->header, 0x7ff); return VOD_OK; }
vod_status_t audio_filter_alloc_state( request_context_t* request_context, mpeg_stream_metadata_t* stream_metadata, void** result) { char filter_desc[sizeof(ATEMPO_FILTER_DESCRIPTION) + 2 * VOD_INT64_LEN]; audio_filter_state_t* state; uint32_t initial_alloc_size; mp4a_config_t codec_config; vod_status_t rc; int ret; if (!initialized) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "audio_filter_alloc_state: module failed to initialize successfully"); return VOD_UNEXPECTED; } if (stream_metadata->media_info.speed_denom != 10) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_alloc_state: unexpected speed denom, must be 10"); return VOD_UNEXPECTED; } // parse the codec config rc = codec_config_mp4a_config_parse( request_context, stream_metadata->media_info.extra_data, stream_metadata->media_info.extra_data_size, &codec_config); if (rc != VOD_OK) { return rc; } // allocate the state state = vod_alloc(request_context->pool, sizeof(*state)); if (state == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "audio_filter_alloc_state: vod_alloc failed"); return VOD_ALLOC_FAILED; } vod_memzero(state, sizeof(*state)); state->request_context = request_context; state->speed_nom = stream_metadata->media_info.speed_nom; state->speed_denom = stream_metadata->media_info.speed_denom; state->output = stream_metadata; // init the decoder state->decoder = avcodec_alloc_context3(decoder_codec); if (state->decoder == NULL) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_alloc_state: avcodec_alloc_context3 failed (1)"); rc = VOD_ALLOC_FAILED; goto error; } state->decoder->codec_tag = stream_metadata->media_info.format; state->decoder->bit_rate = stream_metadata->media_info.bitrate; state->decoder->time_base.num = 1; // Note: changing the timescale in order to revert the speed change that was applied to the frames while parsing the mp4 state->decoder->time_base.den = stream_metadata->media_info.timescale / stream_metadata->media_info.speed_nom * stream_metadata->media_info.speed_denom; state->decoder->pkt_timebase = state->decoder->time_base; state->decoder->extradata = (u_char*)stream_metadata->media_info.extra_data; state->decoder->extradata_size = stream_metadata->media_info.extra_data_size; state->decoder->channels = stream_metadata->media_info.u.audio.channels; state->decoder->bits_per_coded_sample = stream_metadata->media_info.u.audio.bits_per_sample; state->decoder->sample_rate = stream_metadata->media_info.u.audio.sample_rate; state->decoder->channel_layout = 0; if (codec_config.channel_config < ARRAY_ENTRIES(aac_channel_layout)) { state->decoder->channel_layout = aac_channel_layout[codec_config.channel_config]; } ret = avcodec_open2(state->decoder, decoder_codec, NULL); if (ret < 0) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_alloc_state: avcodec_open2(decoder) failed %d", ret); rc = VOD_UNEXPECTED; goto error; } // init the encoder state->encoder = avcodec_alloc_context3(encoder_codec); if (state->encoder == NULL) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_alloc_state: avcodec_alloc_context3 failed (2)"); rc = VOD_ALLOC_FAILED; goto error; } state->encoder->sample_fmt = ENCODER_INPUT_SAMPLE_FORMAT; state->encoder->sample_rate = state->decoder->sample_rate; state->encoder->channel_layout = state->decoder->channel_layout; state->encoder->channels = state->decoder->channels; state->encoder->bit_rate = state->decoder->bit_rate; state->encoder->flags |= CODEC_FLAG_GLOBAL_HEADER; // make the codec generate the extra data ret = avcodec_open2(state->encoder, encoder_codec, NULL); if (ret < 0) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_alloc_state: avcodec_open2(encoder) failed %d", ret); rc = VOD_UNEXPECTED; goto error; } // allocate frames state->decoded_frame = av_frame_alloc(); if (state->decoded_frame == NULL) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_alloc_state: av_frame_alloc failed (1)"); rc = VOD_ALLOC_FAILED; goto error; } state->filtered_frame = av_frame_alloc(); if (state->filtered_frame == NULL) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_alloc_state: av_frame_alloc failed (2)"); rc = VOD_ALLOC_FAILED; goto error; } // initialize the output arrays initial_alloc_size = (stream_metadata->frame_count * stream_metadata->media_info.speed_denom) / stream_metadata->media_info.speed_nom + 10; if (vod_array_init(&state->frames_array, request_context->pool, initial_alloc_size, sizeof(input_frame_t)) != VOD_OK) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "audio_filter_alloc_state: vod_array_init failed (1)"); rc = VOD_ALLOC_FAILED; goto error; } if (vod_array_init(&state->frame_offsets_array, request_context->pool, initial_alloc_size, sizeof(uint64_t)) != VOD_OK) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "audio_filter_alloc_state: vod_array_init failed (2)"); rc = VOD_ALLOC_FAILED; goto error; } // initialize the filter graph vod_sprintf(filter_desc, ATEMPO_FILTER_DESCRIPTION, (int)(stream_metadata->media_info.speed_nom / 10), (int)(stream_metadata->media_info.speed_nom % 10)); rc = audio_filter_init_filters(state, stream_metadata, filter_desc); if (rc != VOD_OK) { goto error; } *result = state; return VOD_OK; error: audio_filter_free_state(state); return rc; }