Ejemplo n.º 1
0
func main() {

	filename := "sample.mp4"

	var (
		pFormatCtx    *avformat.AVFormatContext
		pCodecCtxOrig *avcodec.AVCodecContext
		pCodecCtx     *avcodec.AVCodecContext
		pCodec        *avcodec.AVCodec
		pFrame        *avutil.AVFrame
		pFrameRGB     *avutil.AVFrame
		packet        *avcodec.AVPacket
		//media_type    *avutil.AVMediaType
		sws_ctx       *swscale.SwsContext
		videoStream   int
		frameFinished int
		numBytes      int
		url           string
	)

	// Register all formats and codecs
	avformat.Av_register_all()

	// Open video file
	if avformat.Avformat_open_input(&pFormatCtx, filename, nil, nil) != 0 {
		log.Println("Error: Couldn't open file.")
		return
	}

	// Retrieve stream information
	if avformat.Avformat_find_stream_info(pFormatCtx, nil) < 0 {
		log.Println("Error: Couldn't find stream information.")
		return
	}

	// Dump information about file onto standard error
	avformat.Av_dump_format(pFormatCtx, 0, url, 0)

	// Find the first video stream
	videoStream = -1

	//pFormatCtx->nb_streams
	n := pFormatCtx.Nb_streams()

	//pFormatCtx->streams[]
	s := pFormatCtx.Streams()
	//s2 := avformat.StreamsOne(pFormatCtx, 1)

	log.Print("Number of Streams:", n)

	for i := 0; i < int(n); i++ {
		// pFormatCtx->streams[i]->codec->codec_type
		log.Println("Stream Number:", i)

		//FIX: AVMEDIA_TYPE_VIDEO
		if (*avformat.AVCodecContext)(s.Codec()) != nil {
			videoStream = i
			break
		}
	}

	if videoStream == -1 {
		log.Println("Couldn't find a video stream")
		return
	}

	codec := s.Codec()

	// Get a pointer to the codec context for the video stream
	//pCodecCtxOrig = pFormatCtx.streams[videoStream].codec
	pCodecCtxOrig = (*avcodec.AVCodecContext)(unsafe.Pointer(&codec))
	log.Println("Bit Rate:", pCodecCtxOrig.Bit_rate())
	log.Println("Channels:", pCodecCtxOrig.Channels())
	log.Println("Coded_height:", pCodecCtxOrig.Coded_height())
	log.Println("Coded_width:", pCodecCtxOrig.Coded_width())
	log.Println("Coder_type:", pCodecCtxOrig.Coder_type())
	log.Println("Height:", pCodecCtxOrig.Height())
	log.Println("Profile:", pCodecCtxOrig.Profile())
	log.Println("Width:", pCodecCtxOrig.Width())
	log.Println("Codec ID:", pCodecCtxOrig.Codec_id())

	//C.enum_AVCodecID
	codec_id := pCodecCtxOrig.Codec_id()

	// Find the decoder for the video stream
	pCodec = avcodec.Avcodec_find_decoder(codec_id)
	if pCodec == nil {
		log.Println("Error: Unsupported codec!")
		return // Codec not found
	}

	// Copy context
	pCodecCtx = avcodec.Avcodec_alloc_context3(pCodec)

	if avcodec.Avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0 {
		log.Println("Error: Couldn't copy codec context")
		return // Error copying codec context
	}

	// Open codec
	if avcodec.Avcodec_open2(pCodecCtx, pCodec, nil) < 0 {
		return // Could not open codec
	}

	// Allocate video frame
	pFrame = avutil.Av_frame_alloc()

	// Allocate an AVFrame structure
	if pFrameRGB = avutil.Av_frame_alloc(); pFrameRGB == nil {
		return
	}

	//##TODO
	var a swscale.AVPixelFormat
	var b int
	//avcodec.AVPixelFormat
	//avcodec.PIX_FMT_RGB24
	//avcodec.SWS_BILINEAR

	w := pCodecCtx.Width()
	h := pCodecCtx.Height()
	pix_fmt := pCodecCtx.Pix_fmt()

	// Determine required buffer size and allocate buffer
	numBytes = avcodec.Avpicture_get_size((avcodec.AVPixelFormat)(a), w, h)

	buffer := avutil.Av_malloc(uintptr(numBytes))

	// Assign appropriate parts of buffer to image planes in pFrameRGB
	// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
	// of AVPicture
	avcodec.Avpicture_fill((*avcodec.AVPicture)(unsafe.Pointer(pFrameRGB)), (*uint8)(buffer), (avcodec.AVPixelFormat)(a), w, h)

	// initialize SWS context for software scaling
	sws_ctx = swscale.Sws_getContext(w,
		h,
		(swscale.AVPixelFormat)(pix_fmt),
		w,
		h,
		a,
		b,
		nil,
		nil,
		nil,
	)

	// Read frames and save first five frames to disk
	i := 0

	for avformat.Av_read_frame(pFormatCtx, packet) >= 0 {
		// Is this a packet from the video stream?
		s := packet.Stream_index()
		if s == videoStream {
			// Decode video frame
			avcodec.Avcodec_decode_video2(pCodecCtx, (*avcodec.AVFrame)(unsafe.Pointer(pFrame)), &frameFinished, packet)

			// Did we get a video frame?
			if frameFinished > 0 {
				// Convert the image from its native format to RGB
				d := avutil.Data(pFrame)
				l := avutil.Linesize(pFrame)
				dr := avutil.Data(pFrameRGB)
				lr := avutil.Linesize(pFrameRGB)
				swscale.Sws_scale(sws_ctx,
					d,
					l,
					0,
					h,
					dr,
					lr,
				)

				// Save the frame to disk
				if i <= 5 {
					saveFrame(pFrameRGB, w, h, i)
				}
				i++
			}
		}

		// Free the packet that was allocated by av_read_frame
		avcodec.Av_free_packet(packet)
	}

	// Free the RGB image
	avutil.Av_free(buffer)
	avutil.Av_frame_free(pFrameRGB)

	// Free the YUV frame
	avutil.Av_frame_free(pFrame)

	// Close the codecs
	avcodec.Avcodec_close(pCodecCtx)
	avcodec.Avcodec_close(pCodecCtxOrig)

	// Close the video file
	avformat.Avformat_close_input(pFormatCtx)

}
Ejemplo n.º 2
0
func main() {

	filename := "sample.mp4"

	var (
		ctxtFormat    *avformat.Context
		ctxtSource    *avcodec.Context
		ctxtDest      *avcodec.Context
		videoCodec    *avcodec.Codec
		videoFrame    *avutil.Frame
		videoFrameRGB *avutil.Frame
		packet        *avcodec.Packet
		ctxtSws       *swscale.Context
		videoStream   int
		frameFinished int
		numBytes      int
		url           string
	)
	//media_type    *avutil.MediaType

	// Register all formats and codecs
	avformat.AvRegisterAll()

	// Open video file
	if avformat.AvformatOpenInput(&ctxtFormat, filename, nil, nil) != 0 {
		log.Println("Error: Couldn't open file.")
		return
	}

	// Retrieve stream information
	if ctxtFormat.AvformatFindStreamInfo(nil) < 0 {
		log.Println("Error: Couldn't find stream information.")
		return
	}

	// Dump information about file onto standard error
	ctxtFormat.AvDumpFormat(0, url, 0)

	// Find the first video stream
	videoStream = -1

	//ctxtFormat->nb_streams
	n := ctxtFormat.NbStreams()

	//ctxtFormat->streams[]
	s := ctxtFormat.Streams()
	//s2 := avformat.StreamsOne(ctxtFormat, 1)

	log.Print("Number of Streams:", n)

	for i := 0; i < int(n); i++ {
		// ctxtFormat->streams[i]->codec->codec_type
		log.Println("Stream Number:", i)

		//FIX: AvMEDIA_TYPE_VIDEO
		if (*avformat.CodecContext)(s.Codec()) != nil {
			videoStream = i
			break
		}
	}

	if videoStream == -1 {
		log.Println("Couldn't find a video stream")
		return
	}

	codec := s.Codec()

	// Get a pointer to the codec context for the video stream
	//ctxtSource = ctxtFormat.streams[videoStream].codec
	ctxtSource = (*avcodec.Context)(unsafe.Pointer(&codec))
	log.Println("Bit Rate:", ctxtSource.BitRate())
	log.Println("Channels:", ctxtSource.Channels())
	log.Println("Coded_height:", ctxtSource.CodedHeight())
	log.Println("Coded_width:", ctxtSource.CodedWidth())
	log.Println("Coder_type:", ctxtSource.CoderType())
	log.Println("Height:", ctxtSource.Height())
	log.Println("Profile:", ctxtSource.Profile())
	log.Println("Width:", ctxtSource.Width())
	log.Println("Codec ID:", ctxtSource.CodecId())

	//C.enum_AVCodecID
	codec_id := ctxtSource.CodecId()

	// Find the decoder for the video stream
	videoCodec = avcodec.AvcodecFindDecoder(codec_id)
	if videoCodec == nil {
		log.Println("Error: Unsupported codec!")
		return // Codec not found
	}

	// Copy context
	ctxtDest = videoCodec.AvcodecAllocContext3()

	if ctxtDest.AvcodecCopyContext(ctxtSource) != 0 {
		log.Println("Error: Couldn't copy codec context")
		return // Error copying codec context
	}

	// Open codec
	if ctxtDest.AvcodecOpen2(videoCodec, nil) < 0 {
		return // Could not open codec
	}

	// Allocate video frame
	videoFrame = avutil.AvFrameAlloc()

	// Allocate an Frame structure
	if videoFrameRGB = avutil.AvFrameAlloc(); videoFrameRGB == nil {
		return
	}

	//##TODO
	var a swscale.PixelFormat
	var b int
	//avcodec.PixelFormat
	//avcodec.PIX_FMT_RGB24
	//avcodec.SWS_BILINEAR

	w := ctxtDest.Width()
	h := ctxtDest.Height()
	pix_fmt := ctxtDest.PixFmt()

	// Determine required buffer size and allocate buffer
	numBytes = avcodec.AvpictureGetSize((avcodec.PixelFormat)(a), w, h)

	buffer := avutil.AvMalloc(uintptr(numBytes))

	// Assign appropriate parts of buffer to image planes in videoFrameRGB
	// Note that videoFrameRGB is an Frame, but Frame is a superset
	// of Picture
	avp := (*avcodec.Picture)(unsafe.Pointer(videoFrameRGB))
	avp.AvpictureFill((*uint8)(buffer), (avcodec.PixelFormat)(a), w, h)

	// initialize SWS context for software scaling
	ctxtSws = swscale.SwsGetcontext(w,
		h,
		(swscale.PixelFormat)(pix_fmt),
		w,
		h,
		a,
		b,
		nil,
		nil,
		nil,
	)

	// Read frames and save first five frames to disk
	i := 0

	for ctxtFormat.AvReadFrame(packet) >= 0 {
		// Is this a packet from the video stream?
		s := packet.StreamIndex()
		if s == videoStream {
			// Decode video frame
			ctxtDest.AvcodecDecodeVideo2((*avcodec.Frame)(unsafe.Pointer(videoFrame)), &frameFinished, packet)

			// Did we get a video frame?
			if frameFinished > 0 {
				// Convert the image from its native format to RGB
				d := avutil.Data(videoFrame)
				l := avutil.Linesize(videoFrame)
				dr := avutil.Data(videoFrameRGB)
				lr := avutil.Linesize(videoFrameRGB)
				swscale.SwsScale(ctxtSws,
					d,
					l,
					0,
					h,
					dr,
					lr,
				)

				// Save the frame to disk
				if i <= 5 {
					saveFrame(videoFrameRGB, w, h, i)
				}
				i++
			}
		}

		// Free the packet that was allocated by av_read_frame
		packet.AvFreePacket()
	}

	// Free the RGB image
	avutil.AvFree(buffer)
	avutil.AvFrameFree(videoFrameRGB)

	// Free the YUV frame
	avutil.AvFrameFree(videoFrame)

	// Close the codecs
	ctxtDest.AvcodecClose()
	ctxtSource.AvcodecClose()

	// Close the video file
	ctxtFormat.AvformatCloseInput()

}