static vod_status_t hds_get_sound_info(request_context_t* request_context, media_info_t* media_info, uint8_t* result) { int sound_rate; int sound_size; int sound_type; if (media_info->u.audio.sample_rate <= 8000) { sound_rate = SOUND_RATE_5_5_KHZ; } else if (media_info->u.audio.sample_rate <= 16000) { sound_rate = SOUND_RATE_11_KHZ; } else if (media_info->u.audio.sample_rate <= 32000) { sound_rate = SOUND_RATE_22_KHZ; } else { sound_rate = SOUND_RATE_44_KHZ; } switch (media_info->u.audio.bits_per_sample) { case 8: sound_size = SOUND_SIZE_8_BIT; break; case 16: sound_size = SOUND_SIZE_16_BIT; break; default: vod_log_error(VOD_LOG_ERR, request_context->log, 0, "hds_get_sound_info: unsupported bits per sample %uD", (uint32_t)media_info->u.audio.bits_per_sample); return VOD_BAD_DATA; } switch (media_info->u.audio.channels) { case 1: sound_type = SOUND_TYPE_MONO; break; case 2: sound_type = SOUND_TYPE_STEREO; break; default: vod_log_error(VOD_LOG_ERR, request_context->log, 0, "hds_get_sound_info: unsupported channels %uD", (uint32_t)media_info->u.audio.channels); return VOD_BAD_DATA; } *result = (SOUND_FORMAT_AAC << 4) | (sound_rate << 2) | (sound_size << 1) | (sound_type); return VOD_OK; }
static vod_status_t mp4_decrypt_start_frame(void* ctx, input_frame_t* frame) { mp4_decrypt_state_t* state = ctx; vod_status_t rc; rc = state->frames_source->start_frame(state->frames_source_context, frame); if (rc != VOD_OK) { return rc; } // get the iv if (state->auxiliary_info_pos + MP4_AES_CTR_IV_SIZE > state->auxiliary_info_end) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "mp4_decrypt_start_frame: failed to get iv from auxiliary info"); return VOD_BAD_DATA; } mp4_aes_ctr_set_iv(&state->cipher, state->auxiliary_info_pos); state->auxiliary_info_pos += MP4_AES_CTR_IV_SIZE; if (!state->use_subsamples) { state->encrypted_bytes = UINT_MAX; return VOD_OK; } // get the subsample info if (state->auxiliary_info_pos + sizeof(uint16_t) + sizeof(cenc_sample_auxiliary_data_subsample_t) > state->auxiliary_info_end) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "mp4_decrypt_start_frame: failed to get subsample info from auxiliary info"); return VOD_BAD_DATA; } read_be16(state->auxiliary_info_pos, state->subsample_count); if (state->subsample_count <= 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "mp4_decrypt_start_frame: invalid subsample count"); return VOD_BAD_DATA; } read_be16(state->auxiliary_info_pos, state->clear_bytes); read_be32(state->auxiliary_info_pos, state->encrypted_bytes); state->subsample_count--; return VOD_OK; }
vod_status_t rate_filter_create_from_string( request_context_t* request_context, vod_str_t* str, media_clip_t* source, media_clip_rate_filter_t** result) { media_clip_rate_filter_t* filter; vod_int_t nom; nom = vod_atofp(str->data, str->len, 2); if (nom < 0) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "rate_filter_create_from_string: failed to parse playback rate \"%V\", expecting a float with up to 2 digits precision", str); return VOD_BAD_REQUEST; } if (nom < 50 || nom > 200) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "rate_filter_create_from_string: invalid playback rate value %i/100, must be between 0.5 and 2", nom); return VOD_BAD_REQUEST; } filter = vod_alloc(request_context->pool, sizeof(*filter) + sizeof(filter->base.sources[0])); if (filter == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "rate_filter_create_from_string: vod_alloc failed"); return VOD_ALLOC_FAILED; } filter->base.parent = NULL; filter->base.sources = (void*)(filter + 1); filter->base.sources[0] = source; filter->base.source_count = 1; filter->base.type = MEDIA_CLIP_RATE_FILTER; filter->base.audio_filter = &rate_filter; filter->rate.nom = nom; filter->rate.denom = 100; source->parent = &filter->base; *result = filter; return VOD_OK; }
static vod_status_t edash_packager_init_stsd_writer_context( request_context_t* request_context, uint32_t media_type, raw_atom_t* original_stsd, bool_t has_clear_lead, u_char* default_kid, stsd_writer_context_t* result) { result->media_type = media_type; result->has_clear_lead = has_clear_lead; result->default_kid = default_kid; if (original_stsd->size < original_stsd->header_size + sizeof(stsd_atom_t) + sizeof(stsd_entry_header_t)) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "edash_packager_init_stsd_writer_context: invalid stsd size %uL", original_stsd->size); return VOD_BAD_DATA; } result->original_stsd_entry = (stsd_entry_header_t*)(original_stsd->ptr + original_stsd->header_size + sizeof(stsd_atom_t)); result->original_stsd_entry_size = parse_be32(result->original_stsd_entry->size); result->original_stsd_entry_format = parse_be32(result->original_stsd_entry->format); if (result->original_stsd_entry_size < sizeof(stsd_entry_header_t)) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "edash_packager_init_stsd_writer_context: invalid stsd entry size %uD", result->original_stsd_entry_size); return VOD_BAD_DATA; } result->tenc_atom_size = ATOM_HEADER_SIZE + sizeof(tenc_atom_t); result->schi_atom_size = ATOM_HEADER_SIZE + result->tenc_atom_size; result->schm_atom_size = ATOM_HEADER_SIZE + sizeof(schm_atom_t); result->frma_atom_size = ATOM_HEADER_SIZE + sizeof(frma_atom_t); result->sinf_atom_size = ATOM_HEADER_SIZE + result->frma_atom_size + result->schm_atom_size + result->schi_atom_size; result->encrypted_stsd_entry_size = result->original_stsd_entry_size + result->sinf_atom_size; result->stsd_atom_size = ATOM_HEADER_SIZE + sizeof(stsd_atom_t) + result->encrypted_stsd_entry_size; if (has_clear_lead) { result->stsd_atom_size += result->original_stsd_entry_size; } return VOD_OK; }
vod_status_t audio_encoder_flush( void* context) { audio_encoder_state_t* state = context; AVPacket output_packet; vod_status_t rc; int avrc; avrc = avcodec_send_frame(state->encoder, NULL); if (avrc < 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_encoder_flush: avcodec_send_frame failed %d", avrc); return VOD_UNEXPECTED; } for (;;) { av_init_packet(&output_packet); output_packet.data = NULL; // packet data will be allocated by the encoder output_packet.size = 0; avrc = avcodec_receive_packet(state->encoder, &output_packet); if (avrc == AVERROR_EOF) { break; } if (avrc < 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_encoder_flush: avcodec_receive_packet failed %d", avrc); return VOD_UNEXPECTED; } rc = audio_encoder_write_packet(state, &output_packet); av_packet_unref(&output_packet); if (rc != VOD_OK) { return rc; } } return VOD_OK; }
static vod_status_t codec_config_get_avc_codec_name(request_context_t* request_context, media_info_t* media_info) { avcc_config_t* config; u_char* p; if (media_info->extra_data_size < sizeof(avcc_config_t)) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "codec_config_get_avc_codec_name: extra data too small"); return VOD_BAD_DATA; } config = (avcc_config_t*)media_info->extra_data; p = vod_sprintf(media_info->codec_name.data, "%*s.%02uxD%02uxD%02uxD", (size_t)sizeof(uint32_t), &media_info->format, (uint32_t)config->profile, (uint32_t)config->compatibility, (uint32_t)config->level); media_info->codec_name.len = p - media_info->codec_name.data; return VOD_OK; }
vod_status_t mp4_aes_ctr_init( mp4_aes_ctr_state_t* state, request_context_t* request_context, u_char* key) { vod_pool_cleanup_t *cln; state->request_context = request_context; cln = vod_pool_cleanup_add(request_context->pool, 0); if (cln == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "mp4_aes_ctr_init: vod_pool_cleanup_add failed"); return VOD_ALLOC_FAILED; } cln->handler = (vod_pool_cleanup_pt)mp4_aes_ctr_cleanup; cln->data = state; EVP_CIPHER_CTX_init(&state->cipher); if (1 != EVP_EncryptInit_ex(&state->cipher, EVP_aes_128_ecb(), NULL, key, NULL)) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "mp4_aes_ctr_init: EVP_EncryptInit_ex failed"); return VOD_ALLOC_FAILED; } return VOD_OK; }
vod_status_t aes_cbc_encrypt_write( aes_cbc_encrypt_context_t* state, u_char* buffer, uint32_t size) { int out_size; u_char* encrypted_buffer; encrypted_buffer = vod_alloc(state->request_context->pool, aes_round_to_block(size)); if (encrypted_buffer == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, state->request_context->log, 0, "aes_cbc_encrypt_write: vod_alloc failed"); return VOD_ALLOC_FAILED; } if (1 != EVP_EncryptUpdate(&state->cipher, encrypted_buffer, &out_size, buffer, size)) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "aes_cbc_encrypt_write: EVP_EncryptUpdate failed"); return VOD_UNEXPECTED; } if (out_size == 0) { return VOD_OK; } return state->callback(state->callback_context, encrypted_buffer, out_size); }
vod_status_t sample_aes_avc_start_nal_unit(void* context, int unit_type, uint32_t unit_size) { sample_aes_avc_filter_state_t* state = (sample_aes_avc_filter_state_t*)context; if ((unit_type != AVC_NAL_SLICE && unit_type != AVC_NAL_IDR_SLICE) || unit_size <= MAX_UNENCRYPTED_UNIT_SIZE) { state->encrypt = FALSE; return VOD_OK; } state->encrypt = TRUE; state->cur_offset = 0; state->next_encrypt_offset = FIRST_ENCRYPTED_OFFSET; state->max_encrypt_offset = unit_size - AES_BLOCK_SIZE; state->last_three_bytes = 1; // reset the IV (it is ok to call EVP_EncryptInit_ex several times without cleanup) if (1 != EVP_EncryptInit_ex(&state->cipher, EVP_aes_128_cbc(), NULL, state->key, state->iv)) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "sample_aes_avc_start_nal_unit: EVP_EncryptInit_ex failed"); return VOD_ALLOC_FAILED; } return VOD_OK; }
static void hls_muxer_simulation_reset(hls_muxer_state_t* state) { hls_muxer_stream_state_t* cur_stream; vod_status_t rc; mpegts_encoder_simulated_start_segment(&state->queue); if (state->clips_end > state->clips_start + 1) { state->cur_clip = state->clips_start; rc = hls_muxer_reinit_tracks(state); if (rc != VOD_OK) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "hls_muxer_simulation_reset: unexpected - hls_muxer_reinit_tracks failed %i", rc); } } else { for (cur_stream = state->first_stream; cur_stream < state->last_stream; cur_stream++) { cur_stream->cur_frame_part = *cur_stream->first_frame_part; cur_stream->cur_frame = cur_stream->cur_frame_part.first_frame; cur_stream->next_frame_time_offset = cur_stream->first_frame_time_offset; } } state->cur_frame = NULL; }
void audio_filter_process_init(vod_log_t* log) { avcodec_register_all(); avfilter_register_all(); buffersrc_filter = avfilter_get_by_name(BUFFERSRC_FILTER_NAME); if (buffersrc_filter == NULL) { vod_log_error(VOD_LOG_WARN, log, 0, "audio_filter_process_init: failed to get buffer source filter, audio filtering is disabled"); return; } buffersink_filter = avfilter_get_by_name(BUFFERSINK_FILTER_NAME); if (buffersink_filter == NULL) { vod_log_error(VOD_LOG_WARN, log, 0, "audio_filter_process_init: failed to get buffer sink filter, audio filtering is disabled"); return; } decoder_codec = avcodec_find_decoder(AV_CODEC_ID_AAC); if (decoder_codec == NULL) { vod_log_error(VOD_LOG_WARN, log, 0, "audio_filter_process_init: failed to get AAC decoder, audio filtering is disabled"); return; } encoder_codec = avcodec_find_encoder_by_name(AAC_ENCODER_NAME); if (encoder_codec == NULL) { vod_log_error(VOD_LOG_WARN, log, 0, "audio_filter_process_init: failed to get AAC encoder, audio filtering is disabled. recompile libavcodec with libfdk_aac to enable it"); return; } if (!audio_filter_is_format_supported(encoder_codec, ENCODER_INPUT_SAMPLE_FORMAT)) { vod_log_error(VOD_LOG_WARN, log, 0, "audio_filter_process_init: encoder does not support the required input format, audio filtering is disabled"); return; } initialized = TRUE; }
vod_status_t audio_encoder_write_frame( void* context, AVFrame* frame) { audio_encoder_state_t* state = context; vod_status_t rc; AVPacket output_packet; int avrc; // send frame avrc = avcodec_send_frame(state->encoder, frame); av_frame_unref(frame); if (avrc < 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_encoder_write_frame: avcodec_send_frame failed %d", avrc); return VOD_UNEXPECTED; } // receive packet av_init_packet(&output_packet); output_packet.data = NULL; // packet data will be allocated by the encoder output_packet.size = 0; avrc = avcodec_receive_packet(state->encoder, &output_packet); if (avrc == AVERROR(EAGAIN)) { return VOD_OK; } if (avrc < 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_encoder_write_frame: avcodec_receive_packet failed %d", avrc); return VOD_ALLOC_FAILED; } rc = audio_encoder_write_packet(state, &output_packet); av_packet_unref(&output_packet); return rc; }
static vod_status_t audio_filter_choose_source(audio_filter_state_t* state, audio_filter_source_t** result) { audio_filter_source_t* sources_cur; audio_filter_source_t* best_source; int failed_requests_max; int failed_requests; int ret; vod_status_t rc; for (;;) { ret = avfilter_graph_request_oldest(state->filter_graph); if (ret < 0) { break; } rc = audio_filter_read_filter_sink(state); if (rc != VOD_OK) { return rc; } } if (ret != AVERROR(EAGAIN)) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_choose_source: avfilter_graph_request_oldest failed %d", ret); return VOD_UNEXPECTED; } failed_requests_max = -1; best_source = NULL; for (sources_cur = state->sources; sources_cur < state->sources_end; sources_cur++) { if (sources_cur->cur_frame >= sources_cur->cur_frame_part.last_frame) { if (sources_cur->cur_frame_part.next == NULL) { continue; } sources_cur->cur_frame_part = *sources_cur->cur_frame_part.next; sources_cur->cur_frame = sources_cur->cur_frame_part.first_frame; } failed_requests = av_buffersrc_get_nb_failed_requests(sources_cur->buffer_src); if (failed_requests > failed_requests_max) { failed_requests_max = failed_requests; best_source = sources_cur; } } *result = best_source; return VOD_OK; }
vod_status_t mss_playready_get_fragment_writer( segment_writer_t* result, request_context_t* request_context, media_set_t* media_set, uint32_t segment_index, segment_writer_t* segment_writer, const u_char* iv, bool_t size_only, vod_str_t* fragment_header, size_t* total_fragment_size) { uint32_t media_type = media_set->sequences[0].media_type; vod_status_t rc; switch (media_type) { case MEDIA_TYPE_VIDEO: return mp4_encrypt_video_get_fragment_writer( result, request_context, media_set, segment_index, mss_playready_video_write_fragment_header, segment_writer, iv); case MEDIA_TYPE_AUDIO: rc = mp4_encrypt_audio_get_fragment_writer( result, request_context, media_set, segment_index, segment_writer, iv); if (rc != VOD_OK) { return rc; } rc = mss_playready_audio_build_fragment_header( result->context, size_only, fragment_header, total_fragment_size); if (rc != VOD_OK) { return rc; } return VOD_OK; } vod_log_error(VOD_LOG_ERR, request_context->log, 0, "mss_playready_get_fragment_writer: invalid media type %uD", media_type); return VOD_UNEXPECTED; }
vod_status_t dash_packager_build_init_mp4( request_context_t* request_context, media_set_t* media_set, bool_t size_only, atom_writer_t* extra_moov_atoms_writer, atom_writer_t* stsd_atom_writer, vod_str_t* result) { init_mp4_sizes_t sizes; u_char* p; // get the result size dash_packager_init_mp4_calc_size( media_set, extra_moov_atoms_writer, stsd_atom_writer, &sizes); // head request optimization if (size_only) { result->len = sizes.total_size; return VOD_OK; } // allocate the buffer result->data = vod_alloc(request_context->pool, sizes.total_size); if (result->data == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "dash_packager_build_init_mp4: vod_alloc failed"); return VOD_ALLOC_FAILED; } // write the init mp4 p = dash_packager_init_mp4_write( result->data, request_context, media_set, &sizes, extra_moov_atoms_writer, stsd_atom_writer); result->len = p - result->data; if (result->len != sizes.total_size) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "dash_packager_build_init_mp4: result length %uz different than allocated length %uz", result->len, sizes.total_size); return VOD_UNEXPECTED; } return VOD_OK; }
vod_status_t audio_filter_alloc_state( request_context_t* request_context, mpeg_stream_metadata_t* stream_metadata, void** result) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_alloc_state: audio filtering not supported, recompile with avcodec/avfilter to enable it"); return VOD_UNEXPECTED; }
vod_status_t audio_filter_alloc_state( request_context_t* request_context, media_sequence_t* sequence, media_clip_t* clip, media_track_t* output_track, size_t* cache_buffer_count, void** result) { audio_filter_init_context_t init_context; vod_status_t rc; // get the source count and graph desc size init_context.request_context = request_context; init_context.graph_desc_size = 0; init_context.source_count = 0; init_context.output_frame_count = 0; rc = audio_filter_walk_filters_prepare_init(&init_context, &clip, 100, 100); if (rc != VOD_OK) { return rc; } if (clip == NULL || init_context.source_count <= 0) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_alloc_state: unexpected - no sources found"); return VOD_UNEXPECTED; } if (clip->type == MEDIA_CLIP_SOURCE) { // got left with a source, following a mix of a single source, nothing to do return VOD_OK; } vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_alloc_state: audio filtering not supported, recompile with avcodec/avfilter to enable it"); return VOD_UNEXPECTED; }
vod_status_t audio_filter_alloc_state( request_context_t* request_context, read_cache_state_t* read_cache_state, media_clip_t* clip, media_track_t* output_track, void** result) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "audio_filter_alloc_state: audio filtering not supported, recompile with avcodec/avfilter to enable it"); return VOD_UNEXPECTED; }
void audio_encoder_process_init(vod_log_t* log) { #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 18, 100) avcodec_register_all(); #endif encoder_codec = avcodec_find_encoder_by_name(AAC_ENCODER_NAME); if (encoder_codec == NULL) { vod_log_error(VOD_LOG_WARN, log, 0, "audio_encoder_process_init: failed to get AAC encoder, audio encoding is disabled. recompile libavcodec with libfdk_aac to enable it"); return; } if (!audio_encoder_is_format_supported(encoder_codec, AUDIO_ENCODER_INPUT_SAMPLE_FORMAT)) { vod_log_error(VOD_LOG_WARN, log, 0, "audio_encoder_process_init: encoder does not support the required input format, audio encoding is disabled"); return; } initialized = TRUE; }
vod_status_t aes_cbc_encrypt_init( aes_cbc_encrypt_context_t** context, request_context_t* request_context, write_callback_t callback, void* callback_context, const u_char* key, const u_char* iv) { aes_cbc_encrypt_context_t* state; vod_pool_cleanup_t *cln; state = vod_alloc(request_context->pool, sizeof(*state)); if (state == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "aes_cbc_encrypt_init: vod_alloc failed"); return VOD_ALLOC_FAILED; } cln = vod_pool_cleanup_add(request_context->pool, 0); if (cln == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "aes_cbc_encrypt_init: vod_pool_cleanup_add failed"); return VOD_ALLOC_FAILED; } cln->handler = (vod_pool_cleanup_pt)aes_cbc_encrypt_cleanup; cln->data = state; state->callback = callback; state->callback_context = callback_context; state->request_context = request_context; EVP_CIPHER_CTX_init(&state->cipher); if (1 != EVP_EncryptInit_ex(&state->cipher, EVP_aes_128_cbc(), NULL, key, iv)) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "aes_cbc_encrypt_init: EVP_EncryptInit_ex failed"); return VOD_ALLOC_FAILED; } *context = state; return VOD_OK; }
vod_status_t hds_packager_build_bootstrap( request_context_t* request_context, media_set_t* media_set, vod_str_t* result) { hds_segment_durations_t segment_durations; segmenter_conf_t* segmenter_conf = media_set->segmenter_conf; vod_status_t rc; size_t result_size; rc = segmenter_conf->get_segment_durations( request_context, segmenter_conf, media_set, NULL, MEDIA_TYPE_NONE, &segment_durations.durations); if (rc != VOD_OK) { return rc; } hds_scale_segment_durations(&segment_durations); result_size = hds_get_abst_atom_size(media_set, &segment_durations); result->data = vod_alloc(request_context->pool, result_size); if (result->data == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "hds_packager_build_bootstrap: vod_alloc failed"); return VOD_ALLOC_FAILED; } result->len = hds_write_abst_atom(result->data, media_set, &segment_durations) - result->data; if (result->len > result_size) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "hds_packager_build_bootstrap: result length %uz exceeded allocated length %uz", result->len, result_size); return VOD_UNEXPECTED; } return VOD_OK; }
static vod_status_t mp4_encrypt_video_init_track(mp4_encrypt_video_state_t* state, media_track_t* track) { state->nal_packet_size_length = track->media_info.u.video.nal_packet_size_length; if (state->nal_packet_size_length < 1 || state->nal_packet_size_length > 4) { vod_log_error(VOD_LOG_ERR, state->base.request_context->log, 0, "mp4_encrypt_video_init_track: invalid nal packet size length %uD", state->nal_packet_size_length); return VOD_BAD_DATA; } state->cur_state = STATE_PACKET_SIZE; state->length_bytes_left = state->nal_packet_size_length; state->packet_size_left = 0; return VOD_OK; }
vod_status_t mp4_aes_ctr_process(mp4_aes_ctr_state_t* state, u_char* dest, const u_char* src, uint32_t size) { const u_char* src_end = src + size; const u_char* cur_end_pos; u_char* encrypted_counter_pos; int out_size; while (src < src_end) { if (state->block_offset == 0) { if (1 != EVP_EncryptUpdate( &state->cipher, state->encrypted_counter, &out_size, state->counter, sizeof(state->counter)) || out_size != sizeof(state->encrypted_counter)) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "mp4_aes_ctr_process: EVP_EncryptUpdate failed"); return VOD_UNEXPECTED; } mp4_aes_ctr_increment_be64(state->counter + 8); } encrypted_counter_pos = state->encrypted_counter + state->block_offset; cur_end_pos = src + MP4_AES_CTR_COUNTER_SIZE - state->block_offset; cur_end_pos = vod_min(cur_end_pos, src_end); state->block_offset += cur_end_pos - src; state->block_offset &= (MP4_AES_CTR_COUNTER_SIZE - 1); while (src < cur_end_pos) { *dest++ = *src++ ^ *encrypted_counter_pos++; } } return VOD_OK; }
vod_status_t aes_cbc_encrypt_flush(aes_cbc_encrypt_context_t* state) { int last_block_len; if (1 != EVP_EncryptFinal_ex(&state->cipher, state->last_block, &last_block_len)) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "aes_cbc_encrypt_flush: EVP_EncryptFinal_ex failed"); return VOD_UNEXPECTED; } if (last_block_len == 0) { return VOD_OK; } return state->callback(state->callback_context, state->last_block, last_block_len); }
buffer_pool_t* buffer_pool_create(vod_pool_t* pool, vod_log_t* log, size_t buffer_size, size_t count) { buffer_pool_t* buffer_pool; u_char* cur_buffer; void* head; if ((buffer_size & 0x0F) != 0) { vod_log_error(VOD_LOG_ERR, log, 0, "buffer_pool_create: invalid size %uz must be a multiple of 16", buffer_size); return NULL; } buffer_pool = vod_alloc(pool, sizeof(*buffer_pool)); if (buffer_pool == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, log, 0, "buffer_pool_create: vod_alloc failed (1)"); return NULL; } cur_buffer = vod_alloc(pool, buffer_size * count); if (cur_buffer == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, log, 0, "buffer_pool_create: vod_alloc failed (2)"); return NULL; } head = NULL; for (; count > 0; count--, cur_buffer += buffer_size) { next_buffer(cur_buffer) = head; head = cur_buffer; } buffer_pool->size = buffer_size; buffer_pool->head = head; return buffer_pool; }
static int64_t segmenter_align_to_key_frames( align_to_key_frames_context_t* context, int64_t offset, int64_t limit) { int64_t cur_duration; for (; context->offset < offset; context->cur_pos++) { if ((void*)context->cur_pos >= context->part->last) { if (context->part->next == NULL) { return limit; } context->part = context->part->next; context->cur_pos = context->part->first; } cur_duration = *context->cur_pos; if (cur_duration <= 0 || cur_duration > MAX_CLIP_DURATION) { vod_log_error(VOD_LOG_WARN, context->request_context->log, 0, "segmenter_align_to_key_frames: ignoring invalid key frame duration %L", cur_duration); continue; } context->offset += cur_duration; if (context->offset >= limit) { return limit; } } return vod_min(context->offset, limit); }
static vod_status_t mp4_encrypt_start_frame(mp4_encrypt_state_t* state) { // make sure we have a frame if (state->cur_frame >= state->last_frame) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "mp4_encrypt_start_frame: no more frames"); return VOD_BAD_DATA; } // get the frame size state->frame_size_left = state->cur_frame->size; state->cur_frame++; // set and increment the iv mp4_aes_ctr_set_iv(&state->cipher, state->iv); mp4_aes_ctr_increment_be64(state->iv); return VOD_OK; }
static void hls_muxer_simulation_reset(hls_muxer_state_t* state) { hls_muxer_stream_state_t* cur_stream; vod_status_t rc; mpegts_encoder_simulated_start_segment(&state->queue); if (state->media_set->clip_count > 1) { state->first_clip_track = state->media_set->filtered_tracks; rc = hls_muxer_reinit_tracks(state); if (rc != VOD_OK) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "hls_muxer_simulation_reset: unexpected - hls_muxer_reinit_tracks failed %i", rc); } // need to explicitly reset the id3 stream since reinit tracks skips it cur_stream = state->last_stream - 1; if (cur_stream->media_type == MEDIA_TYPE_NONE) { cur_stream->cur_frame_part = *cur_stream->first_frame_part; cur_stream->cur_frame = cur_stream->cur_frame_part.first_frame; cur_stream->next_frame_time_offset = cur_stream->first_frame_time_offset; } } else { for (cur_stream = state->first_stream; cur_stream < state->last_stream; cur_stream++) { cur_stream->cur_frame_part = *cur_stream->first_frame_part; cur_stream->cur_frame = cur_stream->cur_frame_part.first_frame; cur_stream->source = get_frame_part_source_clip(cur_stream->cur_frame_part); cur_stream->next_frame_time_offset = cur_stream->first_frame_time_offset; } } state->cur_frame = NULL; }
static vod_status_t audio_filter_flush_encoder(audio_filter_state_t* state) { AVPacket output_packet; vod_status_t rc; int got_packet; int avrc; for (;;) { av_init_packet(&output_packet); output_packet.data = NULL; // packet data will be allocated by the encoder output_packet.size = 0; got_packet = 0; avrc = avcodec_encode_audio2(state->sink.encoder, &output_packet, NULL, &got_packet); if (avrc < 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_flush_encoder: avcodec_encode_audio2 failed %d", avrc); return VOD_UNEXPECTED; } if (!got_packet) { break; } rc = audio_filter_write_frame(state, &output_packet); av_free_packet(&output_packet); if (rc != VOD_OK) { return rc; } } return audio_filter_update_track(state); }
vod_status_t audio_encoder_update_media_info( void* context, media_info_t* media_info) { audio_encoder_state_t* state = context; AVCodecContext *encoder = state->encoder; u_char* new_extra_data; if (encoder->time_base.num != 1) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_encoder_update_media_info: unexpected encoder time base %d/%d", encoder->time_base.num, encoder->time_base.den); return VOD_UNEXPECTED; } media_info->timescale = encoder->time_base.den; media_info->bitrate = encoder->bit_rate; media_info->u.audio.object_type_id = 0x40; // ffmpeg always writes 0x40 (ff_mp4_obj_type) media_info->u.audio.channels = encoder->channels; media_info->u.audio.bits_per_sample = AUDIO_ENCODER_BITS_PER_SAMPLE; media_info->u.audio.packet_size = 0; // ffmpeg always writes 0 (mov_write_audio_tag) media_info->u.audio.sample_rate = encoder->sample_rate; new_extra_data = vod_alloc(state->request_context->pool, encoder->extradata_size); if (new_extra_data == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, state->request_context->log, 0, "audio_encoder_update_media_info: vod_alloc failed"); return VOD_ALLOC_FAILED; } vod_memcpy(new_extra_data, encoder->extradata, encoder->extradata_size); media_info->extra_data.data = new_extra_data; media_info->extra_data.len = encoder->extradata_size; return VOD_OK; }