2019. 6. 3. 18:41ㆍProgramming/Android
MediaMuxer를 대신해서 FFmpeg를 사용하여 MP4 컨테이너를 씌우는 예제를 검색하다가, 깃허브에서 [ffmpeg-muxer, Akagi201](https://github.com/Akagi201/ffmpeg-muxer/blob/master/main.c) 코드를 발견했다. 정확히 Muxing을 하는 코드여서, 이 코드를 사용하여 테스트해보기로 한다.
[삽질기록] RAW H.264(AVC)에 MP4컨테이너 씌우기 #2 / FFmpeg 빌드에서 muxer/demuxer모듈이 추가된 ffmpeg 라이브러리를 적용하고 빌드하니, 중간에 Got signal 에러를 뱉고는 앱이 멈춰버린다. 원인을 보니 오디오 파일을 입력하지 않았는데, 이로 인해서 코드 중간에 오동작이 발생해서 앱이 크러쉬되는 것이었다.
위의 ffmpeg-muxer 코드의 main에서 오디오 파일을 사용하는 부분은 다음과 같다.
if ((ret = avformat_open_input(&ifmt_ctx_a, in_filename_a, 0, 0)) < 0) { LOG("Could not open input file."); goto end; } if ((ret = avformat_find_stream_info(ifmt_ctx_a, 0)) < 0) { LOG("Failed to retrieve input stream information"); goto end; }
오디오 파일의 경로를 참조하여, 파일을 여는 코드다.
int audioindex_a = -1, audioindex_out = -1; for (i = 0; i < ifmt_ctx_a->nb_streams; i++) { // Create output AVStream according to input AVStream if (ifmt_ctx_a->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { audioindex_a = i; AVStream *in_stream = ifmt_ctx_a->streams[i]; AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec); if (!out_stream) { LOG("Failed allocating output stream"); ret = AVERROR_UNKNOWN; goto end; } audioindex_out = out_stream->index; // Copy the settings of AVCodecContext if (avcodec_copy_context(out_stream->codec, in_stream->codec) < 0) { LOG("Failed to copy context from input to output stream codec context"); goto end; } out_stream->codec->codec_tag = 0; if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; break; } }
오디오 파일을 아웃풋 스트림으로 복사하는 코드다.
if (av_compare_ts(cur_pts_v, ifmt_ctx_v->streams[videoindex_v]->time_base, cur_pts_a, ifmt_ctx_a->streams[audioindex_a]->time_base) <= 0) { ifmt_ctx = ifmt_ctx_v; stream_index = videoindex_out; if (av_read_frame(ifmt_ctx, &pkt) >= 0) { do { if (pkt.stream_index == videoindex_v) { cur_pts_v = pkt.pts; break; } } while (av_read_frame(ifmt_ctx, &pkt) >= 0); } else { break; } } else { ifmt_ctx = ifmt_ctx_a; stream_index = audioindex_out; if (av_read_frame(ifmt_ctx, &pkt) >= 0) { do { if (pkt.stream_index == audioindex_a) { cur_pts_a = pkt.pts; break; } } while (av_read_frame(ifmt_ctx, &pkt) >= 0); } else { break; } }
오디오 파일과 비디오 파일의 각 프레임에 기록되어있는 타임스탬프를 비교하여, 해당 프레임을 복사하는 코드이다.
대충 위에서 오디오와 관련된 구문을 주석처리하고나니, RAW파일이 MP4로 변환되어 잘 동작하는 걸 확인할 수 있다. :)
이제 H265 RAW파일을 MP4로 변환하는 코드와, 오디오 파일을 MUXING하는 코드만 작성하면 동작상의 문제는 해결될 듯 했다.
안드로이드의 라이프사이클과 관련된 문제는 그 이후에 해결하면 될 듯 했다.
'Programming > Android' 카테고리의 다른 글
cURL을 Android에서 사용하기 위해 Shared Library(libcurl.so)로 빌드하기(32bits/64bits/without-ssl) (0) | 2019.06.13 |
---|---|
[삽질기록] RAW H.264(AVC)에 MP4컨테이너 씌우기 #4 / FFmpeg 재빌드(64bits) (0) | 2019.06.10 |
[삽질기록] RAW H.264(AVC)에 MP4컨테이너 씌우기 #2 / FFmpeg 빌드 (0) | 2019.06.03 |
[삽질기록] RAW H.264(AVC)에 MP4컨테이너 씌우기 #1 (4) | 2019.05.29 |
Flutter 관련 자료 정리 (0) | 2019.05.26 |