#include "ffutil.h" #include #include extern "C"{ #include #include } static void imgCleanupHandler(void *info) { delete [] (uchar*)info; } QString videoInfo(QByteArray url, QImage &img, int64_t *dur, AVCodecID *codec_id) { AVFormatContext *fmt_ctx = avformat_alloc_context(); QString err; { if(avformat_open_input(&fmt_ctx, url.constData(), 0, 0) != 0) { err = "Couldn't open input stream"; goto free; } if(avformat_find_stream_info(fmt_ctx, 0) < 0) { err = "Couldn't find stream information"; goto free; } if(dur) *dur = fmt_ctx->duration; int vi_idx = -1; for(uint ss=0; ssnb_streams; ss++) if(fmt_ctx->streams[ss]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {vi_idx = ss; break;} if(vi_idx == -1) { err = "Didn't find a Video Stream"; goto free; } auto codecpar = fmt_ctx->streams[vi_idx]->codecpar; if(codec_id) *codec_id = codecpar->codec_id; qDebug()<<"codecpar w h"<width<<"x"<height<<"codec_id"<codec_id<codec_id); if(av_seek_frame(fmt_ctx, -1, 1000000, AVSEEK_FLAG_BACKWARD) < 0) { err = "av_seek_frame fail"; goto free; } const AVCodec *decoder = avcodec_find_decoder(codecpar->codec_id); if(decoder==0) { err = "Could not found Video Decoder"; goto free; } auto vcCtx = avcodec_alloc_context3(decoder); avcodec_parameters_to_context(vcCtx, codecpar); if(avcodec_open2(vcCtx, decoder, 0) < 0) { err = "Could not open Video Codec Ctx"; avcodec_free_context(&vcCtx); goto free; } auto sws_ctx = sws_getContext(vcCtx->width, vcCtx->height, vcCtx->pix_fmt, vcCtx->width, vcCtx->height, AV_PIX_FMT_RGB32, SWS_FAST_BILINEAR, 0, 0, 0); auto packet = av_packet_alloc(); auto frm = av_frame_alloc(); int dstStride[4]{(vcCtx->width*4+63)/64*64}; dstStride[3] = dstStride[0] * vcCtx->height; uint8_t *dst[4]{0}; while(1) { if(av_read_frame(fmt_ctx, packet) < 0) break; if(packet->stream_index != vi_idx) continue; int res = avcodec_send_packet(vcCtx, packet); if(res < 0) break; while((res = avcodec_receive_frame(vcCtx, frm)) != AVERROR(EAGAIN)) { if(res < 0) goto free2; dst[0] = new uchar[dstStride[3]]; sws_scale(sws_ctx, frm->data, frm->linesize, 0, vcCtx->height, dst, dstStride); img = QImage(dst[0], vcCtx->width, vcCtx->height, dstStride[0], QImage::Format_ARGB32, imgCleanupHandler, dst[0]); goto free2; } } free2: av_frame_free(&frm); av_packet_free(&packet); avcodec_free_context(&vcCtx); sws_freeContext(sws_ctx); } free: avformat_close_input(&fmt_ctx); return err; } QString audioInfo(QByteArray url, int64_t *dur) { AVFormatContext *fmt_ctx = avformat_alloc_context(); QString err; { if(avformat_open_input(&fmt_ctx, url.constData(), nullptr, nullptr) != 0) { err = "Couldn't open input stream"; goto free; } if(avformat_find_stream_info(fmt_ctx, nullptr) < 0) { err = "Couldn't find stream information"; goto free; } if(dur!=nullptr) *dur = fmt_ctx->duration; } free: avformat_close_input(&fmt_ctx); return err; }