static vod_status_t audio_filter_update_track(audio_filter_state_t* state) { media_track_t* output = state->output; input_frame_t* cur_frame; input_frame_t* last_frame; uint32_t old_timescale; vod_status_t rc; u_char* new_extra_data; bool_t has_frames; if (state->sink.encoder->time_base.num != 1) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_update_track: unexpected encoder time base %d/%d", state->sink.encoder->time_base.num, state->sink.encoder->time_base.den); return VOD_UNEXPECTED; } // decrement the old frame count and size state->sequence->total_frame_count -= output->frame_count; state->sequence->total_frame_size -= output->total_frames_size; output->total_frames_size = 0; output->total_frames_duration = 0; // update frames output->frame_count = state->frames_array.nelts; output->frames.first_frame = state->frames_array.elts; output->frames.last_frame = output->frames.first_frame + output->frame_count; output->frames.next = NULL; // check whether there are any frames with duration has_frames = FALSE; // Note: always a single part here last_frame = output->frames.last_frame; for (cur_frame = output->frames.first_frame; cur_frame < last_frame; cur_frame++) { if (cur_frame->duration != 0) { has_frames = TRUE; break; } } if (!has_frames) { output->frames.first_frame = NULL; output->frames.last_frame = NULL; output->frame_count = 0; return VOD_OK; } // update the frames source to memory rc = frames_source_memory_init(state->request_context, &output->frames.frames_source_context); if (rc != VOD_OK) { return rc; } output->frames.frames_source = &frames_source_memory; // calculate the total frames size and duration output->media_info.min_frame_duration = 0; for (cur_frame = output->frames.first_frame; cur_frame < last_frame; cur_frame++) { output->total_frames_size += cur_frame->size; output->total_frames_duration += cur_frame->duration; if (cur_frame->duration != 0 && (output->media_info.min_frame_duration == 0 || cur_frame->duration < output->media_info.min_frame_duration)) { output->media_info.min_frame_duration = cur_frame->duration; } } // update media info old_timescale = output->media_info.timescale; output->media_info.timescale = state->sink.encoder->time_base.den; output->media_info.duration = rescale_time(output->media_info.duration, old_timescale, output->media_info.timescale); output->media_info.bitrate = state->sink.encoder->bit_rate; output->media_info.u.audio.object_type_id = 0x40; // ffmpeg always writes 0x40 (ff_mp4_obj_type) output->media_info.u.audio.channels = state->sink.encoder->channels; output->media_info.u.audio.bits_per_sample = ENCODER_BITS_PER_SAMPLE; output->media_info.u.audio.packet_size = 0; // ffmpeg always writes 0 (mov_write_audio_tag) output->media_info.u.audio.sample_rate = state->sink.encoder->sample_rate; output->key_frame_count = 0; output->first_frame_time_offset = rescale_time(output->first_frame_time_offset, old_timescale, output->media_info.timescale); new_extra_data = vod_alloc(state->request_context->pool, state->sink.encoder->extradata_size); if (new_extra_data == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, state->request_context->log, 0, "audio_filter_update_track: vod_alloc failed"); return VOD_ALLOC_FAILED; } vod_memcpy(new_extra_data, state->sink.encoder->extradata, state->sink.encoder->extradata_size); output->media_info.extra_data.data = new_extra_data; output->media_info.extra_data.len = state->sink.encoder->extradata_size; if (output->media_info.codec_name.data != NULL) { rc = codec_config_get_audio_codec_name(state->request_context, &output->media_info); if (rc != VOD_OK) { return rc; } } // add the new frame count and size state->sequence->total_frame_count += output->frame_count; state->sequence->total_frame_size += output->total_frames_size; // TODO: update raw_atoms return VOD_OK; }
vod_status_t audio_filter_update_stream_metadata(audio_filter_state_t* state) { mpeg_stream_metadata_t* output = state->output; input_frame_t* cur_frame; input_frame_t* last_frame; uint32_t old_timescale; vod_status_t rc; u_char* new_extra_data; if (state->encoder->time_base.num != 1) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_update_stream_metadata: unexpected encoder time base num %d", state->encoder->time_base.num); return VOD_UNEXPECTED; } output->frames = state->frames_array.elts; output->frame_count = state->frames_array.nelts; output->frame_offsets = state->frame_offsets_array.elts; output->total_frames_size = 0; output->total_frames_duration = 0; output->media_info.min_frame_duration = 0; output->media_info.max_frame_duration = 0; last_frame = output->frames + output->frame_count; for (cur_frame = output->frames; cur_frame < last_frame; cur_frame++) { output->total_frames_size += cur_frame->size; output->total_frames_duration += cur_frame->duration; if (cur_frame->duration != 0 && (output->media_info.min_frame_duration == 0 || cur_frame->duration < output->media_info.min_frame_duration)) { output->media_info.min_frame_duration = cur_frame->duration; } if (cur_frame->duration > output->media_info.max_frame_duration) { output->media_info.max_frame_duration = cur_frame->duration; } } if (output->media_info.min_frame_duration == 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "audio_filter_update_stream_metadata: min frame duration is zero"); return VOD_UNEXPECTED; } old_timescale = output->media_info.timescale; output->media_info.timescale = state->encoder->time_base.den; output->media_info.duration = rescale_time(output->media_info.duration, old_timescale, output->media_info.timescale); output->media_info.bitrate = state->encoder->bit_rate; output->media_info.speed_nom = 1; output->media_info.speed_denom = 1; output->media_info.u.audio.object_type_id = 0x40; // ffmpeg always writes 0x40 (ff_mp4_obj_type) output->media_info.u.audio.channels = state->encoder->channels; output->media_info.u.audio.bits_per_sample = ENCODER_BITS_PER_SAMPLE; output->media_info.u.audio.packet_size = 0; // ffmpeg always writes 0 (mov_write_audio_tag) output->media_info.u.audio.sample_rate = state->encoder->sample_rate; output->key_frame_count = 0; output->first_frame_time_offset = rescale_time(output->first_frame_time_offset, old_timescale, output->media_info.timescale); new_extra_data = vod_alloc(state->request_context->pool, state->encoder->extradata_size); if (new_extra_data == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, state->request_context->log, 0, "audio_filter_update_stream_metadata: vod_alloc failed"); return VOD_ALLOC_FAILED; } vod_memcpy(new_extra_data, state->encoder->extradata, state->encoder->extradata_size); output->media_info.extra_data = new_extra_data; output->media_info.extra_data_size = state->encoder->extradata_size; if (output->media_info.codec_name.data != NULL) { rc = codec_config_get_audio_codec_name(state->request_context, &output->media_info); if (rc != VOD_OK) { return rc; } } output->frames_file_index = INVALID_FILE_INDEX; // the frames are now in memory // TODO: update raw_atoms return VOD_OK; }