__int64 index_context = 0, last_start_pts=0;
std::list<AVFormatContext*> ifmt_ctx_lst;
AVFormatContext *ofmt_ctx = nullptr, *ifmt_ctx = nullptr;
void BeginSplitFile(const char* file, const char* out_file)
{
index_context = 0;
AVFormatContext* ifmt_ctx_item = nullptr;
if ((avformat_open_input(&ifmt_ctx_item, file, 0, 0)) < 0)
return;
ifmt_ctx_lst.push_back(ifmt_ctx_item);
if ((avformat_find_stream_info(ifmt_ctx_item, 0)) < 0)
return;
if (ofmt_ctx != nullptr) return;
avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_file);
if (!ofmt_ctx) return;
for (unsigned int i = 0; i < ifmt_ctx_item->nb_streams; i++) {
AVStream *out_stream, *in_stream = ifmt_ctx_item->streams[i];
AVCodecParameters *in_codecpar = in_stream->codecpar;
out_stream = avformat_new_stream(ofmt_ctx, NULL);
if (!out_stream) return;
if (avcodec_parameters_copy(out_stream->codecpar, in_codecpar) < 0)
return;
out_stream->codecpar->codec_tag = 0;
}
if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)){
if (avio_open(&ofmt_ctx->pb, out_file, AVIO_FLAG_WRITE) < 0)
return;
}
if (avformat_write_header(ofmt_ctx, NULL) < 0)
return;
}
void SplitFile(double from, double to)
{
std::list<AVFormatContext*>::iterator it = ifmt_ctx_lst.begin();
std::advance(it, index_context);
AVFormatContext* ifmt_ctx_item = *it;
index_context++;
if (!ifmt_ctx_item || av_seek_frame(ifmt_ctx_item, -1, (__int64)from * AV_TIME_BASE, AVSEEK_FLAG_ANY) < 0)
return;
__int64 start_pts = -1;
for (int i = 0;; i++){
AVPacket pkt;
AVStream *in_stream, *out_stream;
if (!ifmt_ctx_item || av_read_frame(ifmt_ctx_item, &pkt) < 0)
break;
in_stream = ifmt_ctx_item->streams[pkt.stream_index];
out_stream = ofmt_ctx->streams[pkt.stream_index];
double time_stamp = av_q2d(in_stream->time_base) * pkt.pts;
if (time_stamp > to){
last_start_pts = pkt.pts - start_pts;
break;
}
if (start_pts == -1) start_pts = pkt.pts;
pkt.pts = av_rescale_q_rnd(pkt.pts - start_pts + last_start_pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.dts = av_rescale_q_rnd(pkt.dts - start_pts + last_start_pts, in_stream->time_base, out_stream->time_base, (AVRounding)(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;
if (!ofmt_ctx || av_interleaved_write_frame(ofmt_ctx, &pkt) < 0)
break;
av_packet_unref(&pkt);
}
}
void EndSplitFile()
{
index_context--;
AVFormatContext* it = ifmt_ctx_lst.front();
if (it) avformat_close_input(&it);
ifmt_ctx_lst.pop_front();
if (ifmt_ctx_lst.size() == 0){
if (ofmt_ctx) av_write_trailer(ofmt_ctx);
if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
avio_closep(&ofmt_ctx->pb);
if (ofmt_ctx) {
avformat_free_context(ofmt_ctx);
ofmt_ctx = nullptr;
}
}
}
__int64 GetFileTimeSpan(const char* file)
{
AVFormatContext *ifmt=avformat_alloc_context();
if(avformat_open_input(&ifmt,file,NULL,NULL)<0)
return -1;
__int64 tduration=ifmt->duration;
avformat_close_input(&ifmt);
avformat_free_context(ifmt);
return tduration / AV_TIME_BASE;
}