int film::process () { int audioSize; uint8_t *buffer; uint8_t *buffer2; int frameFinished; int numBytes; shot s; static struct SwsContext *img_convert_ctx = NULL; create_main_dir (); string graphpath = this->global_path + "/"; g = new graph (600, 400, graphpath, threshold, this); g->set_title ("Motion quantity"); /* * Register all formats and codecs */ av_register_all (); if (av_open_input_file (&pFormatCtx, input_path.c_str (), NULL, 0, NULL) != 0) { string error_msg = "Impossible to open file"; error_msg += input_path; shotlog (error_msg); return -1; // Couldn't open file } /* * Retrieve stream information */ if (av_find_stream_info (pFormatCtx) < 0) return -1; // Couldn't find stream information // dump_format (pFormatCtx, 0, path.c_str (), false); videoStream = -1; audioStream = -1; /* * Detect streams types */ for (int j = 0; j < pFormatCtx->nb_streams; j++) { switch (pFormatCtx->streams[j]->codec->codec_type) { case AVMEDIA_TYPE_VIDEO: videoStream = j; break; case AVMEDIA_TYPE_AUDIO: audioStream = j; break; default: break; } } /* * Get a pointer to the codec context for the video stream */ if (audioStream != -1) { if (audio_set) { string xml_audio = graphpath + "/" + "audio.xml"; init_xml (xml_audio); } pCodecCtxAudio = pFormatCtx->streams[audioStream]->codec; pCodecAudio = avcodec_find_decoder (pCodecCtxAudio->codec_id); if (pCodecAudio == NULL) return -1; // Codec not found if (avcodec_open (pCodecCtxAudio, pCodecAudio) < 0) return -1; // Could not open codec } update_metadata (); /* * Find the decoder for the video stream */ if (videoStream != -1) { pCodecCtx = pFormatCtx->streams[videoStream]->codec; pCodec = avcodec_find_decoder (pCodecCtx->codec_id); if (pCodec == NULL) return -1; // Codec not found if (avcodec_open (pCodecCtx, pCodec) < 0) return -1; // Could not open codec /* * Allocate video frame */ pFrame = avcodec_alloc_frame (); pFrameRGB = avcodec_alloc_frame (); pFrameRGBprev = avcodec_alloc_frame (); /* * Determine required buffer size and allocate buffer */ numBytes = avpicture_get_size (PIX_FMT_RGB24, width, height); buffer = (uint8_t *) malloc (sizeof (uint8_t) * numBytes); buffer2 = (uint8_t *) malloc (sizeof (uint8_t) * numBytes); /* * Assign appropriate parts of buffer to image planes in pFrameRGB */ avpicture_fill ((AVPicture *) pFrameRGB, buffer, PIX_FMT_RGB24, width, height); avpicture_fill ((AVPicture *) pFrameRGBprev, buffer2, PIX_FMT_RGB24, width, height); /* * Mise en place du premier plan */ s.fbegin = 0; s.msbegin = 0; s.myid = 0; shots.push_back (s); } checknumber = (samplerate * samplearg) / 1000; /* * Boucle de traitement principale du flux */ this->frame_number = 0; while (av_read_frame (pFormatCtx, &packet) >= 0) { if (packet.stream_index == videoStream) { AVPacket pkt; av_init_packet (&pkt); pkt.data = packet.data; pkt.size = packet.size; avcodec_decode_video2 (pCodecCtx, pFrame, &frameFinished, &pkt); if (frameFinished) { // Convert the image into RGB24 if (! img_convert_ctx) { img_convert_ctx = sws_getContext(width, height, pCodecCtx->pix_fmt, width, height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL); if (! img_convert_ctx) { fprintf(stderr, "Cannot initialize the conversion context!\n"); exit(1); } } /* API: int sws_scale(SwsContext *c, uint8_t *src, int srcStride[], int srcSliceY, int srcSliceH, uint8_t dst[], int dstStride[] ) */ sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); /* Old API doc (cf http://www.dranger.com/ffmpeg/functions.html ) int img_convert(AVPicture *dst, int dst_pix_fmt, const AVPicture *src, int src_pix_fmt, int src_width, int src_height) */ /* img_convert ((AVPicture *) pFrameRGB, PIX_FMT_RGB24, (AVPicture *) pFrame, pCodecCtx->pix_fmt, width, height); */ this->frame_number ++; /* Si ce n'est pas la permiere image */ if ( this->frame_number > 2) { CompareFrame (pFrameRGB, pFrameRGBprev); } else { /* * Cas ou c'est la premiere image, on cree la premiere image dans tous les cas */ image *begin_i = new image (this, width, height, s.myid, BEGIN); begin_i->create_img_dir (); begin_i->SaveFrame (pFrameRGB); shots.back ().img_begin = begin_i; } memcpy (buffer2, buffer, numBytes); } } if (audio_set && (packet.stream_index == audioStream)) { process_audio (); } /* * Free the packet that was allocated by av_read_frame */ if (packet.data != NULL) av_free_packet (&packet); } if (videoStream != -1) { /* Mise en place de la dernière image */ int lastFrame = this->frame_number; shots.back ().fduration = lastFrame - shots.back ().fbegin; shots.back ().msduration = int (((shots.back ().fduration) * 1000) / fps); duration.mstotal = int (shots.back ().msduration + shots.back ().msbegin); image *end_i = new image (this, width, height, shots.back ().myid, END); end_i->SaveFrame (pFrameRGB); shots.back ().img_end = end_i; /* * Graphe de la qté de mvmt */ g->init_gd (); g->draw_all_canvas (); g->draw_color_datas (); g->draw_datas (); if (video_set) { string xml_color = graphpath + "/" + "video.xml"; g->write_xml (xml_color); } g->save (); /* * Free the RGB images */ free (buffer); free (buffer2); av_free (pFrameRGB); av_free (pFrame); av_free (pFrameRGBprev); avcodec_close (pCodecCtx); } /* * Close the codec */ if (audioStream != -1) { /* Fermetrure du fichier xml */ if (audio_set) close_xml (); avcodec_close (pCodecCtxAudio); } /* * Close the video file */ av_close_input_file (pFormatCtx); }
BOOST_DATA_TEST_CASE(vcm_encdec, make_data_from_tuple_container(vecEncDecClips), src, dst, fmt, config, tolerance) { VideoClip srcClip(src); VideoClip dstClip(dst); DWORD fccCodec = FCC(fmt); BOOST_REQUIRE(srcClip.GetWidth() == dstClip.GetWidth()); BOOST_REQUIRE(srcClip.GetHeight() == dstClip.GetHeight()); DWORD fccSrc = srcClip.GetFourCC(); DWORD fccDst = dstClip.GetFourCC(); unsigned int nWidth = srcClip.GetWidth(); unsigned int nHeight = srcClip.GetHeight(); size_t cbSrcData; size_t cbDstData; size_t cbCompressedData; HIC hicEncode, hicDecode; LRESULT lr; union { BITMAPINFOHEADER bihCompressed; char bihCompressedBuf[128]; }; BITMAPINFOHEADER bihSrc; BITMAPINFOHEADER bihDst; hicEncode = ICOpen(ICTYPE_VIDEO, fccCodec, ICMODE_COMPRESS); BOOST_REQUIRE(hicEncode != NULL); ICCloser iccloserEnc(hicEncode); lr = ICSetState(hicEncode, &config.front(), config.size()); BOOST_REQUIRE(lr == config.size()); hicDecode = ICOpen(ICTYPE_VIDEO, fccCodec, ICMODE_DECOMPRESS); BOOST_REQUIRE(hicDecode != NULL); ICCloser iccloserDec(hicDecode); memset(&bihSrc, 0, sizeof(BITMAPINFOHEADER)); bihSrc.biSize = sizeof(BITMAPINFOHEADER); bihSrc.biWidth = nWidth; bihSrc.biHeight = nHeight; bihSrc.biPlanes = 1; bihSrc.biBitCount = FCC2BitCount(fccSrc); bihSrc.biCompression = FCC2Compression(fccSrc); bihSrc.biSizeImage = 10000000; memset(&bihDst, 0, sizeof(BITMAPINFOHEADER)); bihDst.biSize = sizeof(BITMAPINFOHEADER); bihDst.biWidth = nWidth; bihDst.biHeight = nHeight; bihDst.biPlanes = 1; bihDst.biBitCount = FCC2BitCount(fccDst); bihDst.biCompression = FCC2Compression(fccDst); bihDst.biSizeImage = 10000000; lr = ICCompressGetFormat(hicEncode, &bihSrc, &bihCompressed); BOOST_REQUIRE_EQUAL(lr, ICERR_OK); cbCompressedData = ICCompressGetSize(hicEncode, &bihSrc, &bihCompressed); lr = ICCompressBegin(hicEncode, &bihSrc, &bihCompressed); BOOST_REQUIRE_EQUAL(lr, ICERR_OK); lr = ICDecompressBegin(hicDecode, &bihCompressed, &bihDst); BOOST_REQUIRE_EQUAL(lr, ICERR_OK); void *pSrcData; void *pDstData; void *pEncoderOut = malloc(cbCompressedData); void *pDecoderOut = NULL; int retSrc, retDst; LONG lFrameNum = 0; while ((retSrc = srcClip.GetNextFrame(&pSrcData, &cbSrcData, NULL)) == 0 && (retDst = dstClip.GetNextFrame(&pDstData, &cbDstData, NULL) == 0)) { DWORD dwFlags = 0; lr = ICCompress(hicEncode, 0, &bihCompressed, pEncoderOut, &bihSrc, pSrcData, NULL, &dwFlags, lFrameNum++, 0, 0, &bihSrc, NULL); BOOST_REQUIRE(lr == ICERR_OK); if (pDecoderOut == NULL) pDecoderOut = malloc(cbDstData); lr = ICDecompress(hicDecode, (dwFlags & AVIIF_KEYFRAME) ? 0 : ICDECOMPRESS_NOTKEYFRAME, &bihCompressed, pEncoderOut, &bihDst, pDecoderOut); BOOST_REQUIRE(lr == ICERR_OK); BOOST_CHECK(bihDst.biSizeImage == cbDstData); BOOST_CHECK(CompareFrame(pDstData, pDecoderOut, nWidth, cbDstData, fccDst, tolerance) == 0); } BOOST_CHECK(retSrc != 0 && retDst != 0); if (pDecoderOut != NULL) free(pDecoderOut); free(pEncoderOut); lr = ICDecompressEnd(hicDecode); BOOST_CHECK(lr == ICERR_OK); lr = ICCompressEnd(hicEncode); BOOST_CHECK(lr == ICERR_OK); }