CFilePlugEx::CFilePlugEx(INT uiSocketIndex, UINT uiPkgSize, string&sourcePath, BYTE _type)
: m_sourcePath(sourcePath)
,m_uiPagSize(uiPkgSize)
, m_uiSocketIndex(uiSocketIndex)
, m_pIfmtCtx(nullptr)
,m_type(_type)
{
m_nVideoIndex = -1;
m_nAudioIndex = -1;
m_bIsInitSuccess = false;
m_nBufSize = 0;
m_nBufIndex = 0;
m_bIsInitSuccess = InitFFmepg();
}
CFilePlugEx::~CFilePlugEx()
{
}
bool CFilePlugEx::StartSendAV(std::function<void(char*fileBuf, int len, UINT uiSocketIndex, BYTE _type)> lambdaCallBabck)
{
if (!m_bIsInitSuccess)
{
MessageBox(0, L"FFMEPG 初始化错误\n", L"错误", 0);
return false;
}
if (m_nBufIndex >= m_nBufSize)
{
m_nBufIndex = 0;
m_nBufSize = 0;
if(!ReadFrame(m_avPkt, m_nBufSize)) {
if (m_nBufSize == -1)//读取文件错误,可能读完了流
{
MessageBox(0, L"读取文件错误,可能读完了流\n", L"错误", 0);
return false;
}
if (m_nBufSize == 0)//可能读取了异常数据帧
{
av_free_packet(&m_avPkt);
m_avPkt.size = 0;
return true;
}
}
}
int len1 = m_nBufSize - m_nBufIndex;
if (len1 >m_uiPagSize)//剩余的数据 比预设的大
{
lambdaCallBabck((char*)m_avPkt.data + m_nBufIndex, m_uiPagSize, m_uiSocketIndex, m_type);
m_nBufIndex += m_uiPagSize;
}
if (len1<= m_uiPagSize) //剩余的小于预设值 不完整简单处理发送。
{
lambdaCallBabck((char*)m_avPkt.data + m_nBufIndex, len1, m_uiSocketIndex, m_type);
m_nBufIndex = 0;
m_nBufSize = 0;
av_free_packet(&m_avPkt);
m_avPkt.size = 0;
}
return true;
}
void CFilePlugEx::StopSendAv()
{
av_free_packet(&m_avPkt);
avformat_close_input(&m_pIfmtCtx);
}
bool CFilePlugEx::InitFFmepg()
{
av_register_all();
if ((avformat_open_input(&m_pIfmtCtx, m_sourcePath.c_str(), 0, 0)) < 0) {
TRACE("Could not open input file.\n");
goto end;
}
if ((avformat_find_stream_info(m_pIfmtCtx, 0)) < 0) {
TRACE("Failed to retrieve input stream information\n");
goto end;
}
for (auto i = 0; i < m_pIfmtCtx->nb_streams; i++) {
AVStream *in_stream = m_pIfmtCtx->streams[i];
if (in_stream->codec->codec_id == AV_CODEC_ID_NONE && m_pIfmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
in_stream->codec->codec_id = AV_CODEC_ID_PCM_ALAW;
in_stream->codecpar->codec_id = AV_CODEC_ID_PCM_ALAW;
}
if (m_pIfmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
if (m_nVideoIndex != -1) {
continue;
}
m_nVideoIndex = i;
}
else if (m_pIfmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
if (m_nAudioIndex != -1) {
continue;
}
m_nAudioIndex = i;
}
else {
break;
}
}
if (m_nAudioIndex == -1&& m_nVideoIndex == -1)
{
TRACE("Failed to find stream\n");
goto end;
}
avcodec_register_all();
return true;
end:
avformat_close_input(&m_pIfmtCtx);
return false;
}
int my_av_bsf_filter(const AVBitStreamFilter *filter, AVPacket *pPacket, const AVCodecParameters *src)
{
int ret;
AVBSFContext *ctx = NULL;
if (!filter)
return 0;
ret = av_bsf_alloc(filter, &ctx);
if (ret < 0)
return ret;
ret = avcodec_parameters_copy(ctx->par_in, src);
if (ret < 0)
return ret;
ret = av_bsf_init(ctx);
if (ret < 0)
return ret;
AVPacket pkt = { 0 };
pkt.data = pPacket->data;
pkt.size = pPacket->size;
ret = av_bsf_send_packet(ctx, &pkt);
if (ret < 0)
return ret;
ret = av_bsf_receive_packet(ctx, &pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
return 0;
else if (ret < 0)
return ret;
uint8_t **poutbuf = &(pPacket->data);
int *poutbuf_size = &(pPacket->size);
*poutbuf = (uint8_t*)av_malloc(pkt.size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!*poutbuf) {
av_packet_unref(&pkt);
return AVERROR(ENOMEM);
}
*poutbuf_size = pkt.size;
memcpy(*poutbuf, pkt.data, pkt.size);
av_packet_unref(&pkt);
/* drain all the remaining packets we cannot return */
while (ret >= 0) {
ret = av_bsf_receive_packet(ctx, &pkt);
av_packet_unref(&pkt);
}
av_bsf_free(&ctx);
return 1;
}
bool CFilePlugEx::ReadFrame(AVPacket &pkt, unsigned int &len)
{
const AVBitStreamFilter *pavBitStFilter = av_bsf_get_by_name("h264_mp4toannexb");
AVStream *in_stream;
if (av_read_frame(m_pIfmtCtx, &pkt) < 0)
{
len = -1;
return false;
}
in_stream = m_pIfmtCtx->streams[pkt.stream_index];
if (pkt.stream_index == m_nVideoIndex) {//视频流
if (m_type == 0x10)
{
my_av_bsf_filter(pavBitStFilter, &pkt, in_stream->codecpar);
len = pkt.size;
}
}
else if(pkt.stream_index == m_nAudioIndex)//音频流
{
if (m_type == 0x01)
{
len = pkt.size;
}
}
else//其他类型的,此时还未结束 可能读取异常
{
len = 0;
return false;
}
return true;
}
ffmpeg解封装,学习记录。
最新推荐文章于 2024-07-09 11:27:31 发布