Created
July 20, 2017 03:51
-
-
Save hjhee/5625ac15238b95502c49192f9b1fb980 to your computer and use it in GitHub Desktop.
an example for rtsp to mp4 remuxing without transcoding
This file contains hidden or 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
#include <libavutil/timestamp.h> | |
#include <libavformat/avformat.h> | |
#include <signal.h> | |
#include <unistd.h> | |
#include <pthread.h> | |
#include <errno.h> | |
static volatile int keep_running=1; | |
static AVOutputFormat *ofmt=NULL; | |
static AVFormatContext *ifmt_ctx=NULL, *ofmt_ctx=NULL; | |
static AVPacket pkt; | |
static AVCodecContext *video_dec_ctx=NULL; | |
static AVStream *in_stream=NULL,*out_stream=NULL; | |
const char src_filename[]="rtsp://user:[email protected]/stream1"; | |
const char dst_filename[]="test.mp4"; | |
static int video_stream_idx=-1; | |
static int width, height; | |
static enum AVPixelFormat pix_fmt; | |
static void int_handler(int dummy){ | |
keep_running=0; | |
fprintf(stderr, "\ncatch SIGINT, exiting...\n"); | |
} | |
static int find_video_stream(int *idx, AVFormatContext *fmt, | |
enum AVMediaType type){ | |
int ret, stream_index; | |
ret=av_find_best_stream(ifmt_ctx, type, -1, -1, NULL, 0); | |
if(ret<0){ | |
fprintf(stderr, "Could not find %s stream" | |
" in input file '%s'\n", | |
av_get_media_type_string(type), | |
src_filename | |
); | |
return ret; | |
}else{ | |
*idx=ret; | |
} | |
return 0; | |
} | |
void *timer_thread(void *arg){ | |
fprintf(stderr, "Starting countdown...\n"); | |
sleep(10); | |
fprintf(stderr, "Countdown complete\n"); | |
keep_running=0; | |
pthread_exit(0); | |
} | |
int main(int argc, char **argv){ | |
int ret; | |
signal(SIGINT, int_handler); | |
AVDictionary *opts=NULL; | |
av_register_all(); | |
avformat_network_init(); | |
av_dict_set(&opts, "buffer_size", "655360", 0); | |
if(avformat_open_input(&ifmt_ctx, src_filename, NULL, &opts)<0){ | |
fprintf(stderr, "Could not open source file %s\n", | |
src_filename); | |
goto end; | |
} | |
av_dict_free(&opts); | |
if(avformat_find_stream_info(ifmt_ctx, NULL)<0){ | |
fprintf(stderr, "Could not find stream information\n"); | |
goto end; | |
} | |
if(find_video_stream(&video_stream_idx, ifmt_ctx, | |
AVMEDIA_TYPE_VIDEO)<0){ | |
goto end; | |
} | |
fprintf(stderr, "Input format context:\n"); | |
av_dump_format(ifmt_ctx, 0, src_filename, 0); | |
avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, dst_filename); | |
if(!ofmt_ctx){ | |
fprintf(stderr, "Could not create output context!\n"); | |
goto end; | |
} | |
ofmt=ofmt_ctx->oformat; | |
out_stream=avformat_new_stream(ofmt_ctx, NULL); | |
if(!out_stream){ | |
fprintf(stderr, "Failed allocating output stream\n"); | |
goto end; | |
} | |
if(avcodec_parameters_copy(out_stream->codecpar, | |
ifmt_ctx->streams[video_stream_idx]->codecpar)<0){ | |
fprintf(stderr, "Failed to copy codec parameters\n"); | |
goto end; | |
} | |
out_stream->codecpar->codec_tag=0; | |
fprintf(stderr, "Output format context:\n"); | |
av_dump_format(ofmt_ctx, 0, dst_filename, 1); | |
if(avio_open(&ofmt_ctx->pb, dst_filename, AVIO_FLAG_WRITE)<0){ | |
fprintf(stderr, "Could not open output file '%s'\n", | |
dst_filename); | |
goto end; | |
} | |
if(avformat_write_header(ofmt_ctx, NULL)<0){ | |
fprintf(stderr, "Error occurred when opening output file\n"); | |
goto end; | |
} | |
/* | |
pthread_t tid; | |
int err; | |
err=pthread_create(&tid, NULL, timer_thread, NULL); | |
if(err){ | |
fprintf(stderr, "%s: %s\n", __func__, strerror(err)); | |
goto end; | |
} | |
*/ | |
int found=0; | |
int pts,dts; | |
int64_t cnt=0; | |
fprintf(stderr, "Start remuxing...\n"); | |
while(keep_running){ | |
if(av_read_frame(ifmt_ctx, &pkt)<0) | |
break; | |
if(pkt.stream_index!=video_stream_idx){ | |
av_packet_unref(&pkt); | |
continue; | |
} | |
if(found==0&&pkt.flags&AV_PKT_FLAG_KEY){ | |
// continue; | |
pts=pkt.pts; | |
dts=pkt.dts; | |
found=1; | |
fprintf(stderr, "cnt=%lld\n", cnt); | |
} | |
pkt.pts=cnt; | |
pkt.dts=cnt; | |
pkt.stream_index=0; | |
cnt+=1; | |
/* | |
in_stream=ifmt_ctx->streams[pkt.stream_index]; | |
pkt.stream_index=0; | |
out_stream=ofmt_ctx->streams[pkt.stream_index]; | |
*/ | |
/* | |
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; | |
*/ | |
/* | |
fprintf(stderr, "\n"); | |
fprintf(stderr, "pkt.pts=%lld\n", pkt.pts); | |
fprintf(stderr, "pkt.dts=%lld\n", pkt.dts); | |
fprintf(stderr, "pkt.duration=%lld\n", pkt.duration); | |
*/ | |
if(av_interleaved_write_frame(ofmt_ctx, &pkt)<0){ | |
fprintf(stderr, "Error muxing packet\n"); | |
break; | |
} | |
av_packet_unref(&pkt); | |
} | |
av_write_trailer(ofmt_ctx); | |
fprintf(stderr, "remuxing completed!\n"); | |
end: | |
avformat_close_input(&ifmt_ctx); | |
if(ofmt_ctx) | |
avio_closep(&ofmt_ctx->pb); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment