Muxerandroid.c
#include <jni.h> #include <string.h> #include <stdio.h> #include <android/log.h> #include < libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswscale/swscale.h> #include < libavutil/frame.h> #include <libavutil/pixfmt.h> #define LOG_TAG "Ffmpegsample" #define LOGI (...) __android_log_print (android_log_info,log_tag,__va_args__) #define LOGE (...) __android_log_print (android_log_error,log_tag,__va_args__)/* fix:h.264 in some container format (FLV, MP4, MKV etc.) NE Ed "H264_mp4toannexb" Bitstream filter (BSF) *add Sps,pps in front of IDR frame *add start code ("0,0,0,1") in front
of Nalu H.264 in some container (mpeg2ts) don ' t need this BSF.
*//' 1 ': use H.264 bitstream Filter #define USE_H264BSF 0/* FIX:AAC in some container format (FLV, MP4, MKV etc.) need "Aac_adtstoasc" bitstream filter (BSF) *//' 1 ': Use AAC bitstream filter #define USE_AACBSF 0 jniexport jint jnical L JAVA_COM_EXAMPLE_FFMPegmuxer_muxerandroid_muxering (JNIENV * env, Jclass obj) {Avoutputformat *ofmt = NULL; Input Avformatcontext and Output avformatcontext avformatcontext *ifmt_ctx_v = NULL, *ifmt_ctx_a = Null,*ofmt_ctx = NUL
L
Avpacket PKT;
int ret, I;
int videoindex_v=-1,videoindex_out=-1;
int audioindex_a=-1,audioindex_out=-1;
int frame_index=0;
int64_t cur_pts_v=0,cur_pts_a=0; const char *IN_FILENAME_V = "Cuc_ieschool.ts";//input file URL const char *in_filename_v = "/sdcard/muxer/cuc_ieschool.
H264 ";
const char *in_filename_a = "Cuc_ieschool.mp3";
const char *in_filename_a = "GOWEST.M4A";
const char *in_filename_a = "/SDCARD/MUXER/GOWEST.AAC";
const char *in_filename_a = "Huoyuanjia.mp3";
const char *out_filename = "/sdcard/muxer/test.ts";//output file URL av_register_all (); Input if (ret = Avformat_open_input (&ifmt_ctx_v, in_filename_v, 0, 0)) < 0 {Logi ("Could not open input fil
E. ");
Goto end; } if (ret = avformat_find_stream_info (ifmt_ctx_v, 0)) &Lt
0) {Logi ("Failed to retrieve input stream information");
Goto end; } if (ret = Avformat_open_input (&ifmt_ctx_a, in_filename_a, 0, 0)) < 0 {Logi ("Could not open input file.")
;
Goto end;
The IF (ret = avformat_find_stream_info (ifmt_ctx_a, 0)) < 0) {Logi ("Failed to retrieve input stream information");
Goto end;
} logi ("===========input information==========\n");
Av_dump_format (ifmt_ctx_v, 0, in_filename_v, 0);
Av_dump_format (ifmt_ctx_a, 0, in_filename_a, 0);
Logi ("======================================\n");
Output avformat_alloc_output_context2 (&ofmt_ctx, NULL, NULL, out_filename);
if (!ofmt_ctx) {Logi ("could not create output context\n");
ret = Averror_unknown;
Goto end;
} ofmt = ofmt_ctx->oformat; for (i = 0, i < ifmt_ctx_v->nb_streams; i++) {//create output avstream according to input avstream if (ifmt_ctx_ V->streams[i]->codec->codec_type==avmedia_type_video) {Avstream *in_stream = ifmt_ctx_v->stReams[i];
Avstream *out_stream = Avformat_new_stream (Ofmt_ctx, In_stream->codec->codec);
Videoindex_v=i;
if (!out_stream) {Logi ("Failed Allocating output stream\n");
ret = Averror_unknown;
Goto end;
} videoindex_out=out_stream->index; Copy the settings of Avcodeccontext if (Avcodec_copy_context (Out_stream->codec, In_stream->codec) < 0) {L
OGI ("Failed to copy context from input to output stream codec context\n");
Goto end;
} out_stream->codec->codec_tag = 0; if (Ofmt_ctx->oformat->flags & Avfmt_globalheader) out_stream->codec->flags |= CODEC_FLAG_GLOBAL_
HEADER;
Break (i = 0; i < ifmt_ctx_a->nb_streams; i++) {//create output avstream according to input avstream if (if Mt_ctx_a->streams[i]->codec->codec_type==avmedia_type_audio) {Avstream *in_stream = ifmt_ctx_a->
Streams[i];
Avstream *out_stream = Avformat_new_stream (Ofmt_ctx, In_stream->codec->codec); AudIoindex_a=i;
if (!out_stream) {Logi ("Failed Allocating output stream\n");
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) {
Logi ("Failed to copy context from input to output stream codec context\n");
Goto end;
} out_stream->codec->codec_tag = 0; if (Ofmt_ctx->oformat->flags & Avfmt_globalheader) out_stream->codec->flags |= CODEC_FLAG_GLOBAL_
HEADER;
Break
} logi ("==========output information==========\n");
Av_dump_format (ofmt_ctx, 0, Out_filename, 1);
Logi ("======================================\n"); Open output file if (!) ( Ofmt->flags & Avfmt_nofile)) {if (Avio_open (&OFMT_CTX->PB, Out_filename, Avio_flag_write) < 0) {LO
GI ("Could not open output file '%s '", out_filename);
Goto end; }//write File Header if (Avformat_write_header(Ofmt_ctx, NULL) < 0) {Logi ("Error occurred when opening output file\n");
Goto end;
//fix #if use_h264bsf avbitstreamfiltercontext* h264bsfc = Av_bitstream_filter_init ("H264_mp4toannexb");
#endif #if use_aacbsf avbitstreamfiltercontext* aacbsfc = Av_bitstream_filter_init ("Aac_adtstoasc");
#endif while (1) {Avformatcontext *ifmt_ctx;
int stream_index=0;
Avstream *in_stream, *out_stream; Get an Avpacket 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{In_stream = ifmt_ctx->streams[pkt.stream_index];
Out_stream = ofmt_ctx->streams[stream_index]; if (pkt.stream_index==videoindex_v) {//fix:no pts (Example:raw H.264)//simple Write PTS if (pkt.pts==av_ Nopts_value) {//write PTS avrational time_base1=in_stream->time_base;
Duration between 2 frames (US) int64_t calc_duration= (double) av_time_base/av_q2d (in_stream->r_frame_rate);
Parameters pkt.pts= (Double) (frame_index*calc_duration)/(double) (av_q2d (TIME_BASE1) *av_time_base);
pkt.dts=pkt.pts;
pkt.duration= (Double) calc_duration/(double) (av_q2d (TIME_BASE1) *av_time_base);
frame_index++;
} 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{In_stream = ifmt_ctx->streams[pkt.stream_index];
Out_stream = ofmt_ctx->streams[stream_index];
if (pkt.stream_index==audioindex_a) {//fix:no pts//simple Write pts if (pkt.pts==av_nopts_value) {
Write PTS avrational time_base1=in_stream->time_base; Duration between 2 frAmes (US) int64_t calc_duration= (double) av_time_base/av_q2d (in_stream->r_frame_rate);
Parameters pkt.pts= (Double) (frame_index*calc_duration)/(double) (av_q2d (TIME_BASE1) *av_time_base);
pkt.dts=pkt.pts;
pkt.duration= (Double) calc_duration/(double) (av_q2d (TIME_BASE1) *av_time_base);
frame_index++;
} cur_pts_a=pkt.pts;
Break
}}while (Av_read_frame (Ifmt_ctx, &PKT) >= 0);
}else{break; }//fix:bitstream Filter #if use_h264bsf av_bitstream_filter_filter (H264BSFC, In_stream->codec, NULL, &PK
T.data, &pkt.size, Pkt.data, pkt.size, 0); #endif #if USE_AACBSF av_bitstream_filter_filter (AACBSFC, Out_stream->codec, NULL, &pkt.data, &pkt.size,
Pkt.data, pkt.size, 0); #endif//convert Pts/dts pkt.pts = Av_rescale_q_rnd (pkt.pts, In_stream->time_base, Out_stream->time_base, AV_ Round_near_inf|
Av_round_pass_minmax)); Pkt.dts = Av_rescale_q_rnd (Pkt.dts, In_stream->tiMe_base, Out_stream->time_base, (av_round_near_inf|
Av_round_pass_minmax));
Pkt.duration = Av_rescale_q (pkt.duration, In_stream->time_base, out_stream->time_base);
Pkt.pos =-1;
Pkt.stream_index=stream_index; Logi ("Write 1 Packet.")
Size:%5d ", pkt.size);
Logi ("Write 1 packet.pts--->%11d", pkt.pts);
Write if (Av_interleaved_write_frame (Ofmt_ctx, &PKT) < 0) {Logi ("Error muxing packet\n");
Break
} av_free_packet (&PKT);
}//write File Trailer Av_write_trailer (OFMT_CTX);
#if USE_H264BSF Av_bitstream_filter_close (H264BSFC);
#endif #if USE_AACBSF av_bitstream_filter_close (AACBSFC);
#endif end:avformat_close_input (&IFMT_CTX_V);
Avformat_close_input (&ifmt_ctx_a); /* Close Output */if (Ofmt_ctx &&!)
Ofmt->flags & Avfmt_nofile)) Avio_close (OFMT_CTX->PB);
Avformat_free_context (OFMT_CTX);
if (Ret < 0 && ret!= averror_eof) {logi ("Error occurred.\n");
return-1;
return 0;
}
Android.mk
Local_path: = $ (call My-dir) $ (Warning $ (local_path)) include $ (clear_vars) Local_module: =avcodec-55 local_src_files
: =lib/libavcodec-55.so local_export_c_includes: = $ (Local_path)/libavcodec include $ (prebuilt_shared_library) Include $ (clear_vars) Local_module: =avfilter-3 local_src_files: =lib/libavfilter-3.so local_export_c_includes: = $ ( Local_path)/libavfilter include $ (prebuilt_shared_library) include $ (clear_vars) Local_module: =avformat-55 LOCAL_SRC _files: =lib/libavformat-55.so local_export_c_includes: = $ (Local_path)/libavformat include $ (prebuilt_shared_ LIBRARY) include $ (clear_vars) Local_module: = avutil-52 local_src_files: =lib/libavutil-52.so local_export_c_includes : = $ (Local_path)/libavutil include $ (prebuilt_shared_library) include $ (clear_vars) Local_module: = swresample-0 Local _src_files: =lib/libswresample-0.so local_export_c_includes: = $ (Local_path)/libswresample include $ (PREBUILT_SHARED
_library) include $ (clear_vars) Local_module: = Swscale-2Local_src_files: =lib/libswscale-2.so local_export_c_includes: = $ (Local_path)/libswscale include $ (PREBUILT_SHARED_ LIBRARY) include $ (clear_vars) Local_module: =ffmpeg local_src_files: =MUXERANDROID.C # Local_export_c_includes: = $ (LO Cal_path)/include local_ldlibs: =-llog-ljnigraphics-lz-landroid local_shared_libraries:= libavcodec-55
3 libavformat-55 libavutil-52 libswscale-2 libswresample-0 include $ (build_shared_library)