Last active
August 28, 2018 05:08
-
-
Save moonpfe/513347e59c854bd783c15b249ce77f60 to your computer and use it in GitHub Desktop.
RTSP 카메라에서 수신한 PCMA 오디오를 AAC로 트랜스 코딩하여 fMP4 형식으로 내보내기
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/edc-rtsp.c b/edc-rtsp.c | |
index 161ca75d..6a2fe275 100644 | |
--- a/edc-rtsp.c | |
+++ b/edc-rtsp.c | |
@@ -902,7 +902,7 @@ edc_rtsp_make_audio_frame (EdcRtsp *rtsp, | |
buf = edc_buf_new_for_frame (pkt->size); | |
buf->channel = 0; | |
buf->flags = EDC_BUF_FLAG_AUDIO; | |
- buf->codec_id = rtsp->audio.codec_id; | |
+ buf->codec_id = EDC_CODEC_ALAW; | |
memcpy (buf->data, pkt->data, pkt->size); | |
return buf; | |
@@ -1535,6 +1535,8 @@ edc_rtsp_open_fmt (EdcRtsp *rtsp) | |
else | |
rtsp->audio.make_frame = edc_rtsp_make_audio_frame; | |
} | |
+ | |
+ rtsp->audio.make_frame = edc_rtsp_make_audio_frame; | |
} | |
else if (codecpar->codec_type == AVMEDIA_TYPE_DATA) | |
{ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/mp4serv.c b/src/mp4serv.c | |
index 4b84abc30..206051c7e 100644 | |
--- a/src/mp4serv.c | |
+++ b/src/mp4serv.c | |
@@ -123,21 +123,18 @@ struct _Mp4ServClient | |
struct | |
{ | |
- EdcAdpcm *decoder; | |
+ AVCodecContext *decoder; | |
AVFilterGraph *graph; | |
AVFilterContext *src; | |
AVFilterContext *sink; | |
AVCodecContext *encoder; | |
AVStream *stream; | |
- char *buf; | |
- int buf_len; | |
- int buf_alloc; | |
- | |
int input_sample_fmt; | |
int input_channel_layout; | |
AVRational input_time_base; | |
int sample_rate; | |
+ int output_sample_rate; | |
int64_t rescale_delta_last; | |
} audio; | |
@@ -558,12 +555,18 @@ mp4serv_init_audio (Mp4ServClient *client, | |
return; | |
} | |
- client->audio.decoder = edc_adpcm_new (); | |
- client->audio.buf_alloc = 1920 * 2; | |
- client->audio.buf = g_malloc (client->audio.buf_alloc + AV_INPUT_BUFFER_PADDING_SIZE); | |
- client->audio.buf_len = 0; | |
- client->audio.input_sample_fmt = in_par->format; | |
- client->audio.input_channel_layout = in_par->channel_layout; | |
+ client->audio.decoder = avcodec_alloc_context3 (decoder); | |
+ avcodec_parameters_to_context (client->audio.decoder, in_par); | |
+ | |
+ ret = avcodec_open2 (client->audio.decoder, decoder, NULL); | |
+ if (ret < 0) | |
+ { | |
+ mp4serv_debug (client, "failed to open audio decoder: '%s'(%d)", | |
+ av_err2str (ret), ret); | |
+ return; | |
+ } | |
+ | |
+ avcodec_parameters_from_context (in_par, client->audio.decoder); | |
ret = mp4serv_init_audio_resampling_filter (client, in_par); | |
if (ret < 0) | |
@@ -579,16 +582,11 @@ mp4serv_deinit_audio (Mp4ServClient *client) | |
{ | |
if (client->audio.decoder) | |
{ | |
- edc_adpcm_unref (client->audio.decoder); | |
+ avcodec_free_context (&client->audio.decoder); | |
client->audio.decoder = NULL; | |
} | |
if (client->audio.graph) | |
avfilter_graph_free (&client->audio.graph); | |
- | |
- g_free (client->audio.buf); | |
- client->audio.buf = NULL; | |
- client->audio.buf_alloc = 0; | |
- client->audio.buf_len = 0; | |
} | |
static void | |
@@ -668,6 +666,119 @@ mp4serv_close_transcoder (Mp4ServClient *client, | |
client->ofmt = NULL; | |
} | |
+static uint8_t * | |
+mp4serv_get_extradata (EdcBuf *frame, | |
+ int *extradata_size) | |
+{ | |
+ AVBSFContext *bsf; | |
+ const AVBitStreamFilter *f; | |
+ const enum AVCodecID *ids; | |
+ AVPacket *dst_pkt; | |
+ int avcodec_id; | |
+ int found; | |
+ int ret; | |
+ AVPacket pkt; | |
+ AVPacket *pkt_ref; | |
+ uint8_t *data; | |
+ | |
+ data = NULL; | |
+ if (extradata_size) | |
+ *extradata_size = 0; | |
+ | |
+ f = av_bsf_get_by_name ("extract_extradata"); | |
+ if (!f || !f->codec_ids) | |
+ return data; | |
+ | |
+ avcodec_id = edc_codec_lookup_avcodec_id (frame->codec_id); | |
+ | |
+ found = 0; | |
+ for (ids = f->codec_ids; *ids != AV_CODEC_ID_NONE; ids++) | |
+ { | |
+ if (*ids == avcodec_id) | |
+ { | |
+ found = 1; | |
+ break; | |
+ } | |
+ } | |
+ | |
+ if (!found) | |
+ return data; | |
+ | |
+ bsf = NULL; | |
+ ret = av_bsf_alloc (f, &bsf); | |
+ if (ret < 0) | |
+ return data; | |
+ | |
+ bsf->par_in->codec_id = avcodec_id; | |
+ ret = av_bsf_init (bsf); | |
+ if (ret < 0) | |
+ { | |
+ av_bsf_free (&bsf); | |
+ | |
+ return data; | |
+ } | |
+ | |
+ dst_pkt = av_packet_alloc (); | |
+ pkt_ref = dst_pkt; | |
+ | |
+ av_init_packet (&pkt); | |
+ pkt.data = (uint8_t *) frame->data; | |
+ pkt.size = frame->len; | |
+ if (frame->flags & EDC_BUF_FLAG_KEY_FRAME) | |
+ pkt.flags |= AV_PKT_FLAG_KEY; | |
+ | |
+ ret = av_packet_ref (pkt_ref, &pkt); | |
+ if (ret < 0) | |
+ goto end_of_extract_extradata; | |
+ | |
+ ret = av_bsf_send_packet (bsf, pkt_ref); | |
+ if (ret < 0) | |
+ { | |
+ av_packet_unref (pkt_ref); | |
+ | |
+ goto end_of_extract_extradata; | |
+ } | |
+ | |
+ ret = 0; | |
+ while (ret >= 0) | |
+ { | |
+ uint8_t *extra; | |
+ int extra_size; | |
+ | |
+ ret = av_bsf_receive_packet (bsf, pkt_ref); | |
+ if (ret < 0) | |
+ { | |
+ if (ret != AVERROR (EAGAIN) && ret != AVERROR_EOF) | |
+ break; | |
+ | |
+ continue; | |
+ } | |
+ | |
+ extra = av_packet_get_side_data (pkt_ref, | |
+ AV_PKT_DATA_NEW_EXTRADATA, | |
+ &extra_size); | |
+ if (extra && extra_size > 0) | |
+ { | |
+ data = g_malloc0 (extra_size + AV_INPUT_BUFFER_PADDING_SIZE); | |
+ memcpy (data, extra, extra_size); | |
+ if (extradata_size) | |
+ *extradata_size = extra_size; | |
+ | |
+ av_packet_unref (pkt_ref); | |
+ break; | |
+ } | |
+ | |
+ av_packet_unref (pkt_ref); | |
+ } | |
+ | |
+end_of_extract_extradata: | |
+ | |
+ av_bsf_free (&bsf); | |
+ av_packet_free (&dst_pkt); | |
+ | |
+ return data; | |
+} | |
+ | |
static void | |
mp4serv_init_extradata (Mp4ServClient *client, | |
AVStream *stream) | |
@@ -873,6 +984,14 @@ mp4serv_open_transcoder (Mp4ServClient *client, | |
st->codecpar->format = AV_PIX_FMT_YUV420P; | |
st->codecpar->width = video_width; | |
st->codecpar->height = video_height; | |
+ if (client->video.extradata.data && client->video.extradata.size > 0) | |
+ { | |
+ st->codecpar->extradata_size = client->video.extradata.size; | |
+ st->codecpar->extradata = av_mallocz (client->video.extradata.size + AV_INPUT_BUFFER_PADDING_SIZE); | |
+ memcpy (st->codecpar->extradata, | |
+ client->video.extradata.data, | |
+ client->video.extradata.size); | |
+ } | |
ret = avcodec_parameters_to_context (client->video.codec, st->codecpar); | |
if (ret < 0) | |
@@ -919,8 +1038,8 @@ mp4serv_open_transcoder (Mp4ServClient *client, | |
stream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; | |
stream->codecpar->codec_id = avcodec_id; | |
stream->codecpar->format = AV_SAMPLE_FMT_FLTP; | |
- stream->codecpar->sample_rate = client->audio.sample_rate; | |
- stream->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; | |
+ stream->codecpar->sample_rate = client->audio.output_sample_rate; | |
+ stream->codecpar->channel_layout = AV_CH_LAYOUT_MONO; | |
stream->codecpar->channels = | |
av_get_channel_layout_nb_channels (stream->codecpar->channel_layout); | |
@@ -1345,49 +1464,38 @@ mp4serv_transcode (Mp4ServClient *client, | |
av_ts2str (packet->duration), | |
av_ts2str (packet->pos), | |
packet->size); | |
- do | |
+ | |
+ packet->dts = av_rescale_q (packet->dts, | |
+ client->audio.input_time_base, | |
+ client->audio.decoder->time_base); | |
+ packet->pts = packet->dts; | |
+ | |
+ ret = avcodec_send_packet (client->audio.decoder, packet); | |
+ if (ret < 0 && ret != AVERROR (EAGAIN) && ret != AVERROR_EOF) | |
+ mp4serv_debug (client, "failed to send audio packet to decoder: '%s'(%d)", | |
+ av_err2str (ret), ret); | |
+ | |
+ while (TRUE) | |
{ | |
- AVFrame *frame; | |
- int pcm_len; | |
- int dec_size; | |
AVRational time_base = { 1, client->audio.sample_rate }; | |
+ AVFrame *frame; | |
- dec_size = (packet->size - 4) * 4; | |
- if (dec_size > client->audio.buf_alloc) | |
- { | |
- client->audio.buf_alloc = dec_size + AV_INPUT_BUFFER_PADDING_SIZE; | |
- client->audio.buf = g_realloc (client->audio.buf, | |
- client->audio.buf_alloc); | |
- } | |
+ frame = av_frame_alloc (); | |
- pcm_len = edc_adpcm_decode (client->audio.decoder, | |
- (const uint8_t *) packet->data, | |
- (int16_t *) client->audio.buf, | |
- packet->size); | |
- if (pcm_len <= 0) | |
- break; | |
+ ret = avcodec_receive_frame (client->audio.decoder, frame); | |
+ if (ret < 0) | |
+ { | |
+ if (0 && ret != AVERROR (EAGAIN) && ret != AVERROR_EOF) | |
+ mp4serv_debug (client, "failed to get decoded audio frame: '%s'(%d)", | |
+ av_err2str (ret), ret); | |
- frame = av_frame_alloc (); | |
- frame->pts = packet->pts; | |
- frame->pkt_dts = frame->pts; | |
- frame->channel_layout = client->audio.input_channel_layout; | |
- frame->channels = av_get_channel_layout_nb_channels (frame->channel_layout); | |
- frame->sample_rate = client->audio.sample_rate; | |
- frame->format = client->audio.input_sample_fmt; | |
- frame->nb_samples = pcm_len | |
- / av_get_bytes_per_sample (frame->format) | |
- / frame->channels; | |
- | |
- avcodec_fill_audio_frame (frame, | |
- frame->channels, | |
- frame->format, | |
- (const uint8_t *) client->audio.buf, | |
- client->audio.buf_alloc, | |
- 0); | |
+ av_frame_free (&frame); | |
+ break; | |
+ } | |
- frame->pts = av_rescale_delta (client->audio.input_time_base, | |
+ frame->pts = av_rescale_delta (client->audio.decoder->time_base, | |
frame->pts, | |
- time_base, | |
+ (AVRational) {1, client->audio.decoder->sample_rate }, | |
frame->nb_samples, | |
&client->audio.rescale_delta_last, | |
time_base); | |
@@ -1413,7 +1521,6 @@ mp4serv_transcode (Mp4ServClient *client, | |
av_frame_free (&frame); | |
} | |
- while (0); | |
while (TRUE) | |
{ | |
@@ -2088,22 +2195,25 @@ mp4serv_feed_frame (Mp4ServStream *stream, | |
{ | |
in_par = avcodec_parameters_alloc (); | |
in_par->codec_type = AVMEDIA_TYPE_AUDIO; | |
- in_par->codec_id = edc_codec_lookup_avcodec_id (EDC_CODEC_ADPCM); | |
- in_par->codec_tag = 17; | |
+ in_par->codec_id = edc_codec_lookup_avcodec_id (EDC_CODEC_ALAW); | |
+ //in_par->codec_tag = 17; | |
in_par->format = AV_SAMPLE_FMT_S16; | |
- in_par->bit_rate = 32000; | |
+ //in_par->bit_rate = 32000; | |
in_par->bits_per_coded_sample = 4; | |
in_par->bits_per_raw_sample = 0; | |
in_par->sample_rate = client->audio.sample_rate; | |
in_par->channel_layout = AV_CH_LAYOUT_MONO; | |
in_par->channels = | |
av_get_channel_layout_nb_channels (in_par->channel_layout); | |
- in_par->sample_rate = 8000; | |
- in_par->block_align = 1024; | |
+ //in_par->block_align = 1024; | |
} | |
else | |
in_par = NULL; | |
+ if (!client->video.extradata.data) | |
+ client->video.extradata.data = | |
+ mp4serv_get_extradata (frame, &client->video.extradata.size); | |
+ | |
ret = mp4serv_open_transcoder (client, | |
frame->codec_id, | |
frame->width, | |
@@ -2435,8 +2545,9 @@ mp4serv_new_client (Mp4ServClientType type, | |
break; | |
} | |
- client->use_audio = FALSE; | |
- client->audio.sample_rate = 8000; | |
+ client->use_audio = TRUE; | |
+ client->audio.sample_rate = 44100; | |
+ client->audio.output_sample_rate = 44100; | |
return client; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment