diff options
-rw-r--r-- | decoder.cpp | 49 | ||||
-rw-r--r-- | decoder.h | 2 | ||||
-rw-r--r-- | global.h | 3 | ||||
-rw-r--r-- | markad-standalone.cpp | 76 | ||||
-rw-r--r-- | markad-standalone.h | 1 | ||||
-rw-r--r-- | queue.cpp | 2 | ||||
-rw-r--r-- | streaminfo.cpp | 90 | ||||
-rw-r--r-- | video.cpp | 13 |
8 files changed, 122 insertions, 114 deletions
diff --git a/decoder.cpp b/decoder.cpp index ea0672e..a9fb7b4 100644 --- a/decoder.cpp +++ b/decoder.cpp @@ -126,8 +126,6 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool useMP2, bool h if (video_codec->capabilities & CODEC_CAP_TRUNCATED) video_context->flags|=CODEC_FLAG_TRUNCATED; // we do not send complete frames - video_context->flags|=CODEC_FLAG_EMU_EDGE; // now linesize should be the same as width - video_context->flags|=CODEC_FLAG_GRAY; // only decode grayscale video_context->flags2|=CODEC_FLAG2_FAST; // really? @@ -137,11 +135,11 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool useMP2, bool h { video_context->flags2|=CODEC_FLAG2_CHUNKS; // needed for H264! video_context->skip_loop_filter=AVDISCARD_ALL; // skip deblocking - video_context->skip_frame=AVDISCARD_NONREF; // P/I-frames + av_log_set_level(AV_LOG_FATAL); // H264 decoder is very chatty } else { - video_context->skip_frame=AVDISCARD_NONKEY; // I-frames + video_context->skip_frame=AVDISCARD_NONKEY; // just I-frames } int ret=avcodec_open(video_context, video_codec); @@ -171,6 +169,14 @@ cMarkAdDecoder::cMarkAdDecoder(int RecvNumber, bool useH264, bool useMP2, bool h } else { + + dsyslog("markad [%i]: using codec %s",recvnumber,video_codec->long_name); + + if (video_context->hwaccel) + { + dsyslog("markad [%i]: using hwaccel %s",recvnumber,video_context->hwaccel->name); + } + video_frame = avcodec_alloc_frame(); if (!video_frame) { @@ -224,7 +230,6 @@ cMarkAdDecoder::~cMarkAdDecoder() av_free(mp2_context); } if (audiobuf) free(audiobuf); - SetVideoInfos(NULL,NULL,NULL,NULL); } bool cMarkAdDecoder::DecodeMP2(MarkAdContext *maContext, uchar *espkt, int eslen) @@ -260,7 +265,7 @@ bool cMarkAdDecoder::DecodeMP2(MarkAdContext *maContext, uchar *espkt, int eslen if (audiobufsize>0) { memcpy(audiobuf,Taudiobuf,audiobufsize); - SetAudioInfos(maContext,ac3_context); + SetAudioInfos(maContext,mp2_context); ret=true; avpkt.size-=len; avpkt.data+=len; @@ -273,6 +278,7 @@ bool cMarkAdDecoder::SetAudioInfos(MarkAdContext *maContext, AVCodecContext *Aud { if ((!maContext) || (!Audio_Context)) return false; + maContext->Audio.Info.SampleRate = Audio_Context->sample_rate; maContext->Audio.Info.Channels = Audio_Context->channels; maContext->Audio.Data.SampleBuf=audiobuf; maContext->Audio.Data.SampleBufLen=audiobufsize; @@ -328,7 +334,7 @@ void cMarkAdDecoder::PAR2DAR(AVRational a, AVRational *erg) video_context->height*a.den,1024*1024); } -bool cMarkAdDecoder::SetVideoInfos(MarkAdContext *maContext,AVCodecContext *Video_Context, AVFrame *Video_Frame, AVRational *DAR) +bool cMarkAdDecoder::SetVideoInfos(MarkAdContext *maContext,AVCodecContext *Video_Context, AVFrame *Video_Frame) { if ((!maContext) || (!Video_Context) || (!Video_Frame)) return false; maContext->Video.Data.Valid=false; @@ -347,11 +353,11 @@ bool cMarkAdDecoder::SetVideoInfos(MarkAdContext *maContext,AVCodecContext *Vide maContext->Video.Info.Pict_Type=Video_Context->coded_frame->pict_type; } - if (DAR) - { - maContext->Video.Info.AspectRatio.Num=DAR->num; - maContext->Video.Info.AspectRatio.Den=DAR->den; - } + AVRational dar; + PAR2DAR(Video_Context->sample_aspect_ratio,&dar); + + maContext->Video.Info.AspectRatio.Num=dar.num; + maContext->Video.Info.AspectRatio.Den=dar.den; maContext->Video.Data.Valid=true; return true; @@ -361,6 +367,21 @@ bool cMarkAdDecoder::DecodeVideo(MarkAdContext *maContext,uchar *pkt, int plen) { if (!video_context) return false; + if ((video_context->codec_id==CODEC_ID_H264) && (!video_context->skip_frame)) + { + if (maContext->Video.Info.Pict_Type) + { + if (maContext->Video.Info.Interlaced) + { + video_context->skip_frame=AVDISCARD_BIDIR; // just P/I-frames + } + else + { + video_context->skip_frame=AVDISCARD_NONKEY; // just I-frames + } + } + } + AVPacket avpkt; #if LIBAVCODEC_VERSION_INT >= ((52<<16)+(25<<8)+0) av_init_packet(&avpkt); @@ -399,9 +420,7 @@ bool cMarkAdDecoder::DecodeVideo(MarkAdContext *maContext,uchar *pkt, int plen) { if (last_qscale_table!=video_frame->qscale_table) { - AVRational dar; - PAR2DAR(video_context->sample_aspect_ratio,&dar); - if (SetVideoInfos(maContext,video_context,video_frame,&dar)) ret=true; + if (SetVideoInfos(maContext,video_context,video_frame)) ret=true; last_qscale_table=video_frame->qscale_table; } } @@ -56,7 +56,7 @@ private: void PAR2DAR(AVRational a, AVRational *erg); bool SetVideoInfos(MarkAdContext *maContext,AVCodecContext *Video_Context, - AVFrame *Video_Frame, AVRational *DAR); + AVFrame *Video_Frame); public: bool DecodeVideo(MarkAdContext *maContext, uchar *pkt, int plen); bool DecodeMP2(MarkAdContext *maContext, uchar *espkt, int eslen); @@ -56,6 +56,7 @@ typedef struct MarkAdContext int LogoExtraction; int LogoWidth; int LogoHeight; + MarkAdAspectRatio AspectRatioHint; } StandAlone; struct General @@ -75,6 +76,7 @@ typedef struct MarkAdContext int Pict_Type; // picture type (I,P,B,S,SI,SP,BI) MarkAdAspectRatio AspectRatio; double FramesPerSecond; + bool Interlaced; } Info; struct Data @@ -90,6 +92,7 @@ typedef struct MarkAdContext struct Info { int Channels; // number of audio channels + int SampleRate; } Info; struct Data { diff --git a/markad-standalone.cpp b/markad-standalone.cpp index 4d41ac5..8222920 100644 --- a/markad-standalone.cpp +++ b/markad-standalone.cpp @@ -15,6 +15,8 @@ char logoDirectory[1024]=""; int logoExtraction=-1; int logoWidth=-1; int logoHeight=-1; +bool bDecodeVideo=true; +bool bDecodeAudio=true; void syslog_with_tid(int priority, const char *format, ...) { @@ -80,10 +82,12 @@ void cMarkAdStandalone::SaveFrame(int frame) return; // Write header - fprintf(pFile, "P5\n%d %d\n255\n", macontext.Video.Info.Width,macontext.Video.Info.Height); + fprintf(pFile, "P5\n%d %d\n255\n", macontext.Video.Data.PlaneLinesize[0], + macontext.Video.Info.Height); // Write pixel data - fwrite(macontext.Video.Data.Plane[0],1,macontext.Video.Info.Width*macontext.Video.Info.Height,pFile); + fwrite(macontext.Video.Data.Plane[0],1, + macontext.Video.Data.PlaneLinesize[0]*macontext.Video.Info.Height,pFile); // Close file fclose(pFile); } @@ -118,7 +122,7 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number) if (abort) break; MarkAdMark *mark=NULL; - if ((video_demux) && (video) && (decoder) && (streaminfo)) + if ((video_demux) && (video) && (streaminfo)) { uchar *pkt; int pktlen; @@ -143,11 +147,13 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number) framecnt++; } - if (decoder->DecodeVideo(&macontext,pkt,pktlen)) + bool dRes=true; + if ((decoder) && (bDecodeVideo)) dRes=decoder->DecodeVideo(&macontext,pkt,pktlen); + if (dRes) { if (macontext.Video.Info.Pict_Type==MA_I_TYPE) { - if (macontext.General.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264) + if ((macontext.General.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264) || (!bDecodeVideo)) { lastiframe=framecnt-1; } @@ -155,7 +161,7 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number) { lastiframe=framecnt-2; } - // SaveFrame(lastiframe); // TODO: JUST FOR DEBUGGING! + //SaveFrame(lastiframe); // TODO: JUST FOR DEBUGGING! mark=video->Process(lastiframe); AddMark(mark); } @@ -208,7 +214,7 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number) } } - if ((mp2_demux) && (decoder) && (audio)) + if ((mp2_demux) && (decoder) && (audio) && (bDecodeAudio)) { uchar *pkt; int pktlen; @@ -252,6 +258,12 @@ bool cMarkAdStandalone::ProcessFile(const char *Directory, int Number) void cMarkAdStandalone::Process(const char *Directory) { if (abort) return; + + struct timeval tv1,tv2; + struct timezone tz; + + gettimeofday(&tv1,&tz); + for (int i=1; i<=MaxFiles; i++) { if (abort) break; @@ -264,6 +276,25 @@ void cMarkAdStandalone::Process(const char *Directory) { isyslog("markad [%i]: aborted",recvnumber); } + else + { + gettimeofday(&tv2,&tz); + long sec,usec; + sec=tv2.tv_sec-tv1.tv_sec; + usec=tv2.tv_usec-tv1.tv_usec; + if (usec<0) + { + usec+=1000000; + sec--; + } + double etime,ftime=0,ptime=0; + etime=sec+((double) usec/1000000); + if (etime>0) ftime=framecnt/etime; + if (macontext.Video.Info.FramesPerSecond>0) + ptime=ftime/macontext.Video.Info.FramesPerSecond; + isyslog("markad [%i]: elapsed time %.2fs, %i frames, %.1f fps, %.1f pps",recvnumber, + etime,framecnt,ftime,ptime); + } } bool cMarkAdStandalone::LoadInfo(const char *Directory) @@ -485,6 +516,7 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory) } else { + macontext.General.APid.Num=-1; macontext.General.DPid.Num=-1; macontext.General.VPid.Num=-1; macontext.General.VPid.Type=MARKAD_PIDTYPE_VIDEO_H262; @@ -588,6 +620,9 @@ int usage() "-b --background\n" " markad runs as a background-process\n" " this will be automatically set if called with \"after\"\n" + "-d --disable=<option>\n" + " <option> 1 = disable video 2 = disable audio\n" + " 3 = disable video and audio\n" "-l --logocachedir\n" " directory where logos stored, default /var/lib/markad\n" "-p, --priority level=<priority>\n" @@ -608,8 +643,8 @@ int usage() " markad sends an OSD-Message for start and end\n" "-V --version\n" " print version-info and exit\n" - "--markfile=<markfilename>\n" - " set a different markfile-name\n" + " --markfile=<markfilename>\n" + " set a different markfile-name\n" "\ncmd: one of\n" "- dummy-parameter if called directly\n" "after markad starts to analyze the recording\n" @@ -656,6 +691,7 @@ int main(int argc, char *argv[]) { {"statisticfile",1,0,'s' }, + {"disable", 1, 0, 'd'}, {"logocachedir", 1, 0, 'l'}, {"extractlogo", 1, 0, 'L'}, {"verbose", 0, 0, 'v'}, @@ -681,7 +717,7 @@ int main(int argc, char *argv[]) {0, 0, 0, 0} }; - c = getopt_long (argc, argv, "s:l:vbp:cjoaOSBCVL:", + c = getopt_long (argc, argv, "s:l:vbp:cjoaOSBCVL:d:", long_options, &option_index); if (c == -1) break; @@ -694,6 +730,26 @@ int main(int argc, char *argv[]) if (SysLogLevel>10) SysLogLevel=10; break; + case 'd': + switch (atoi(optarg)) + { + case 1: + bDecodeVideo=false; + break; + case 2: + bDecodeAudio=false; + break; + case 3: + bDecodeVideo=false; + bDecodeAudio=false; + break; + default: + fprintf(stderr, "markad: invalid disable option: %s\n", optarg); + return 2; + break; + } + break; + case 'b': bFork = true; break; diff --git a/markad-standalone.h b/markad-standalone.h index 3323fec..8edf655 100644 --- a/markad-standalone.h +++ b/markad-standalone.h @@ -17,6 +17,7 @@ #include <getopt.h> #include <signal.h> #include <ctype.h> +#include <sys/time.h> #include "demux.h" #include "global.h" @@ -205,7 +205,7 @@ int cMarkAdPaketQueue::FindAudioHeader(int Start, int *FrameSize, int *HeaderSiz scanner|=buffer[i]; } if (i==inptr) return -1; - i-=2; + if (AC3) i-=2; if (AC3) { diff --git a/streaminfo.cpp b/streaminfo.cpp index bad7a0e..30deea5 100644 --- a/streaminfo.cpp +++ b/streaminfo.cpp @@ -7,7 +7,7 @@ */ #include "streaminfo.h" - +#include <stdio.h> cMarkAdStreamInfo::cMarkAdStreamInfo() { memset(&H264,0,sizeof(H264)); @@ -236,8 +236,10 @@ bool cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt, num_units_in_tick = bs.getU32(); // num_units_in_tick time_scale = bs.getU32(); // time_scale if (num_units_in_tick > 0) + { frame_rate = time_scale / (2*num_units_in_tick); - + if (H264.frame_mbs_only_flag) frame_rate/=2; + } //bs.skipBit(); // fixed_frame_rate_flag } /* @@ -409,8 +411,11 @@ bool cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt, bs.skipBits(2); // colour_plane_id } bs.skipBits(H264.log2_max_frame_num); // frame_num + + maContext->Video.Info.Interlaced=false; if (!H264.frame_mbs_only_flag) { + maContext->Video.Info.Interlaced=true; bool field_pic_flag=bs.getBit(); if (field_pic_flag) { @@ -612,87 +617,6 @@ unsigned TemporalReferenceL: return false; } -/* -// taken from ffmpeg -int cMarkAdStreamInfo::nalUnescape(uint8_t *dst, const uint8_t *src, int length) -{ - int i; - -#if HAVE_FAST_UNALIGNED -# if HAVE_FAST_64BIT -# define RS 7 - for (i=0; i+1<length; i+=9) - { - if (!((~*(const uint64_t*)(src+i) & (*(const uint64_t*)(src+i) - 0x0100010001000101ULL)) & 0x8000800080008080ULL)) -# else -# define RS 3 - for (i=0; i+1<length; i+=5) - { - if (!((~*(const uint32_t*)(src+i) & (*(const uint32_t*)(src+i) - 0x01000101U)) & 0x80008080U)) -# endif - continue; - if (i>0 && !src[i]) i--; - while (src[i]) i++; -#else -# define RS 0 - for (i=0; i+1<length; i+=2) - { - if (src[i]) continue; - if (i>0 && src[i-1]==0) i--; -#endif - if (i+2<length && src[i+1]==0 && src[i+2]<=3) - { - if (src[i+2]!=3) - { - // startcode, so we must be past the end - length=i; - } - break; - } - i-= RS; - } - - memcpy(dst,src,i); - - if (i>=length-1) //no escaped 0 - { - return length; - } - - int si,di; - si=di=i; - while (si+2<length) - { - //remove escapes (very rare 1:2^22) - if (src[si+2]>3) - { - dst[di++]= src[si++]; - dst[di++]= src[si++]; - } - else if (src[si]==0 && src[si+1]==0) - { - if (src[si+2]==3) //escape - { - dst[di++]= 0; - dst[di++]= 0; - si+=3; - continue; - } - else //next start code - goto nsc; - } - - dst[di++]= src[si++]; - } - while (si<length) - dst[di++]= src[si++]; -nsc: - - return di; -} -*/ - - // taken from femon int cMarkAdStreamInfo::nalUnescape(uint8_t *dst, const uint8_t *src, int len) { @@ -165,10 +165,12 @@ int cMarkAdLogo::Detect(int lastiframe, int *logoiframe) { for (int X=xstart; X<=xend-1; X++) { - area.source[(X-xstart)+(Y-ystart)*LOGOWIDTH]=macontext->Video.Data.Plane[0][X+(Y*macontext->Video.Info.Width)]; + area.source[(X-xstart)+(Y-ystart)*LOGOWIDTH]= + macontext->Video.Data.Plane[0][X+(Y*macontext->Video.Data.PlaneLinesize[0])]; SUMA+=area.source[(X-xstart)+(Y-ystart)*LOGOWIDTH]; } } + SUMA/=(LOGOWIDTH*LOGOHEIGHT); #if 0 if (SUMA>=100) @@ -222,7 +224,8 @@ int cMarkAdLogo::Detect(int lastiframe, int *logoiframe) for (int J=-1; J<=1; J++) { sumX=sumX+ (int) ((*(macontext->Video.Data.Plane[0]+X+I+ - (Y+J)*macontext->Video.Info.Width))*GX[I+1][J+1]); + (Y+J)*macontext->Video.Data.PlaneLinesize[0])) + *GX[I+1][J+1]); } } @@ -232,7 +235,8 @@ int cMarkAdLogo::Detect(int lastiframe, int *logoiframe) for (int J=-1; J<=1; J++) { sumY=sumY+ (int) ((*(macontext->Video.Data.Plane[0]+X+I+ - (Y+J)*macontext->Video.Info.Width))*GY[I+1][J+1]); + (Y+J)*macontext->Video.Data.PlaneLinesize[0]))* + GY[I+1][J+1]); } } @@ -247,7 +251,8 @@ int cMarkAdLogo::Detect(int lastiframe, int *logoiframe) area.sobel[(X-xstart)+(Y-ystart)*LOGOWIDTH]=val; - area.result[(X-xstart)+(Y-ystart)*LOGOWIDTH]=(area.mask[(X-xstart)+(Y-ystart)*LOGOWIDTH] + val) & 255; + area.result[(X-xstart)+(Y-ystart)*LOGOWIDTH]= + (area.mask[(X-xstart)+(Y-ystart)*LOGOWIDTH] + val) & 255; if (!area.result[(X-xstart)+(Y-ystart)*LOGOWIDTH]) area.rpixel++; |