diff --git a/src/driver/record.cpp b/src/driver/record.cpp index b642a6b74..b608b2ada 100644 --- a/src/driver/record.cpp +++ b/src/driver/record.cpp @@ -1882,9 +1882,11 @@ void CStreamRec::Close() } avformat_free_context(ofcx); } - + if (bsfc) + av_bitstream_filter_close(bsfc); ifcx = NULL; ofcx = NULL; + bsfc = NULL; } void CStreamRec::GetPids(CZapitChannel * channel) @@ -1939,7 +1941,7 @@ void CStreamRec::FillMovieInfo(CZapitChannel * /*channel*/, APIDList & /*apid_li recMovieInfo->epgVideoPid = st->id; if (codec->codec_id == AV_CODEC_ID_H264) recMovieInfo->VideoType = 1; - printf("%s: [VIDEO] 0x%x \n", __FUNCTION__, recMovieInfo->epgVideoPid); + printf("%s: [VIDEO] 0x%x\n", __FUNCTION__, recMovieInfo->epgVideoPid); } } } @@ -2085,7 +2087,11 @@ bool CStreamRec::Open(CZapitChannel * channel) printf("%s: Cannot find stream info [%s]!\n", __FUNCTION__, channel->getUrl().c_str()); return false; } - if (!strstr(ifcx->iformat->name, "applehttp") && !strstr(ifcx->iformat->name, "mpegts")) { + if (!strstr(ifcx->iformat->name, "applehttp") && + !strstr(ifcx->iformat->name, "mpegts") && + !strstr(ifcx->iformat->name, "matroska") && + !strstr(ifcx->iformat->name, "avi") && + !strstr(ifcx->iformat->name, "mp4")) { printf("%s: not supported format [%s]!\n", __FUNCTION__, ifcx->iformat->name); return false; } @@ -2132,6 +2138,9 @@ bool CStreamRec::Open(CZapitChannel * channel) av_log_set_level(AV_LOG_VERBOSE); av_dump_format(ofcx, 0, ofcx->filename, 1); av_log_set_level(AV_LOG_WARNING); + bsfc = av_bitstream_filter_init("h264_mp4toannexb"); + if (!bsfc) + printf("%s: av_bitstream_filter_init h264_mp4toannexb failed!\n", __FUNCTION__); return true; } @@ -2156,6 +2165,25 @@ void CStreamRec::run() break; if (pkt.stream_index < 0) continue; + + AVCodecContext *codec = ifcx->streams[pkt.stream_index]->codec; + if (bsfc && codec->codec_id == CODEC_ID_H264) { + AVPacket newpkt = pkt; + + int len; + if ((len = av_bitstream_filter_filter(bsfc, codec, NULL, &newpkt.data, &newpkt.size, pkt.data, pkt.size, pkt.flags & AV_PKT_FLAG_KEY)) < 0) { + av_free_packet(&pkt); + continue; + } + + av_free_packet(&pkt); + + newpkt.buf = av_buffer_create(newpkt.data, newpkt.size, av_buffer_default_free, NULL, 0); + pkt = newpkt; + } + pkt.pts = av_rescale_q(pkt.pts, ifcx->streams[pkt.stream_index]->time_base, ofcx->streams[pkt.stream_index]->time_base); + pkt.dts = av_rescale_q(pkt.dts, ifcx->streams[pkt.stream_index]->time_base, ofcx->streams[pkt.stream_index]->time_base); + av_write_frame(ofcx, &pkt); av_free_packet(&pkt); diff --git a/src/driver/record.h b/src/driver/record.h index 440de6d2a..d5d5c4495 100644 --- a/src/driver/record.h +++ b/src/driver/record.h @@ -242,6 +242,7 @@ class CStreamRec : public CRecordInstance, OpenThreads::Thread private: AVFormatContext *ifcx; AVFormatContext *ofcx; + AVBitStreamFilterContext *bsfc; bool stopped; bool interrupt; time_t time_started; diff --git a/src/driver/streamts.cpp b/src/driver/streamts.cpp index 1554ce230..6ef96b9c5 100644 --- a/src/driver/streamts.cpp +++ b/src/driver/streamts.cpp @@ -749,8 +749,12 @@ void CStreamStream::Close() if (avio_ctx) av_free(avio_ctx); + if (bsfc) + av_bitstream_filter_close(bsfc); + ifcx = NULL; ofcx = NULL; + bsfc = NULL; avio_ctx = NULL; } @@ -788,7 +792,11 @@ bool CStreamStream::Open() printf("%s: Cannot find stream info [%s]!\n", __FUNCTION__, channel->getUrl().c_str()); return false; } - if (!strstr(ifcx->iformat->name, "applehttp") && !strstr(ifcx->iformat->name, "mpegts")) { + if (!strstr(ifcx->iformat->name, "applehttp") && + !strstr(ifcx->iformat->name, "mpegts") && + !strstr(ifcx->iformat->name, "matroska") && + !strstr(ifcx->iformat->name, "avi") && + !strstr(ifcx->iformat->name, "mp4")) { printf("%s: not supported format [%s]!\n", __FUNCTION__, ifcx->iformat->name); return false; } @@ -830,6 +838,9 @@ bool CStreamStream::Open() av_log_set_level(AV_LOG_VERBOSE); av_dump_format(ofcx, 0, ofcx->filename, 1); av_log_set_level(AV_LOG_WARNING); + bsfc = av_bitstream_filter_init("h264_mp4toannexb"); + if (!bsfc) + printf("%s: av_bitstream_filter_init h264_mp4toannexb failed!\n", __FUNCTION__); return true; } @@ -872,6 +883,27 @@ void CStreamStream::run() av_init_packet(&pkt); if (av_read_frame(ifcx, &pkt) < 0) break; + if (pkt.stream_index < 0) + continue; + + AVCodecContext *codec = ifcx->streams[pkt.stream_index]->codec; + if (bsfc && codec->codec_id == CODEC_ID_H264 ) { + AVPacket newpkt = pkt; + + int len; + if ((len = av_bitstream_filter_filter(bsfc, codec, NULL, &newpkt.data, &newpkt.size, pkt.data, pkt.size, pkt.flags & AV_PKT_FLAG_KEY)) < 0) { + av_free_packet(&pkt); + continue; + } + + av_free_packet(&pkt); + + newpkt.buf = av_buffer_create(newpkt.data, newpkt.size, av_buffer_default_free, NULL, 0); + pkt = newpkt; + } + pkt.pts = av_rescale_q(pkt.pts, ifcx->streams[pkt.stream_index]->time_base, ofcx->streams[pkt.stream_index]->time_base); + pkt.dts = av_rescale_q(pkt.dts, ifcx->streams[pkt.stream_index]->time_base, ofcx->streams[pkt.stream_index]->time_base); + av_write_frame(ofcx, &pkt); av_free_packet(&pkt); } diff --git a/src/driver/streamts.h b/src/driver/streamts.h index 6c6d7dd72..da2708e51 100644 --- a/src/driver/streamts.h +++ b/src/driver/streamts.h @@ -73,6 +73,7 @@ class CStreamStream : public CStreamInstance private: AVFormatContext *ifcx; AVFormatContext *ofcx; + AVBitStreamFilterContext *bsfc; AVIOContext *avio_ctx; bool stopped;