yuv420p-2.yuv

// myf2.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include "stdlib.h"
#include <string.h>
#include <math.h>
#include <chrono> //C++11時間類標準模板庫

extern "C"{

#if _MSC_VER
#define snprintf _snprintf
#endif
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libswscale/swscale.h"
#include "libavutil/frame.h"
#include "libavutil/imgutils.h"

#include "libavutil/adler32.h"
#include "libavutil/imgutils.h"
#include "libavutil/timestamp.h"

}


//////////////////////////////////////////////////////////////////////////

int fun2(int argc, char* argv[])
{
	AVCodec *pCodec = NULL;

	const int in_buffer_size = 4096;
	uint8_t* in_buffer = new uint8_t[4096 + 460800];
	uint8_t *cur_ptr;
	int cur_size;
	int ret, i, got_picture;
	int y_size;
	AVFrame	*pFrame;     //AVFrame存儲一幀解碼後的像素數據
	AVPacket packet;    //存儲一幀(一般情況下)壓縮編碼數據

	enum AVCodecID codec_id = AV_CODEC_ID_H264;
	char filepath_in[] = "data\\net-download-test.264";
	char filepath_out[] = "data\\net-download-test.264.yuv";
	int first_time = 1;

	//註冊所有的編解碼器
	void *opaque = NULL;
	av_demuxer_iterate(&opaque);
	//av_register_all();  被棄用

	//打開多媒體文件
	AVFormatContext *pFormatCtx = NULL;
	//爲AVFormatContext分配內存
	pFormatCtx = avformat_alloc_context();
	if (avformat_open_input(&pFormatCtx, filepath_in, NULL, NULL) != 0){
		return -1;   // Couldn't open file
	}
	//獨立的解碼上下文
	//AVCodecContext視頻解碼的上下文,爲AVCodecContext分配內存
	AVCodecContext *pCodecCtx = avcodec_alloc_context3(pCodec);
	if (!pCodecCtx){
		printf("Could not allocate video codec context\n");
		return -1;
	}

	//循環遍歷所有流,找到視頻流
	int videoStream = -1;
	for (i = 0; i < pFormatCtx->nb_streams; i++) {
		if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
			videoStream = i;
			break;
		}
	}

	//將配置參數複製到AVCodecContext中
	avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStream]->codecpar);

	//查找視頻解碼器
	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
	if (!pCodec) {
		printf("Codec not found\n");
		return -1;
	}

	//打開解碼器
	if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
		printf("Could not open codec\n");
		return -1;
	}

	//初始化AVCodecParserContext
	AVCodecParserContext *pCodecParserCtx = NULL;
	pCodecParserCtx = av_parser_init(codec_id);
	if (!pCodecParserCtx){
		printf("Could not allocate video parser context\n");
		return -1;
	}

	//Input File
	FILE *fp_in = fopen(filepath_in, "rb");
	if (!fp_in) {
		printf("Could not open input stream\n");
		return -1;
	}

	//Output File
	FILE *fp_out = fopen(filepath_out, "wb");
	if (!fp_out) {
		printf("Could not open output YUV file\n");
		return -1;
	}

	//爲AVFrame分配內存
	pFrame = av_frame_alloc();
	//初始化AVPacket
	av_init_packet(&packet);

	int n_frame = 0;
	while (1) {
		cur_size = fread(in_buffer, 1, in_buffer_size, fp_in);
		if (cur_size == 0)
			break;
		cur_ptr = in_buffer;

		while (cur_size > 0){

			//解析獲得一個Packet
			int len = av_parser_parse2(
				pCodecParserCtx, pCodecCtx,
				&packet.data, &packet.size,
				cur_ptr, cur_size,
				AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);

			cur_ptr += len;
			cur_size -= len;

			if (packet.size == 0)
				continue;

			//Some Info from AVCodecParserContext
			printf("[Packet]Size:%6d\t", packet.size);
			switch (pCodecParserCtx->pict_type){
			case AV_PICTURE_TYPE_I: printf("Type:I\t"); break;
			case AV_PICTURE_TYPE_P: printf("Type:P\t"); break;
			case AV_PICTURE_TYPE_B: printf("Type:B\t"); break;
			default: printf("Type:Other\t"); break;
			}
			printf("Number:%4d\n", pCodecParserCtx->output_picture_number);

			//解碼一幀數據
			//avcodec_send_packet()向解碼器提供輸入AVPacket
			ret = avcodec_send_packet(pCodecCtx, &packet);
			if (ret != 0)
			{
				return -1;
			}
			//avcodec_receive_frame()接收解碼的幀AVFrame
			while (avcodec_receive_frame(pCodecCtx, pFrame) == 0)
			{
				got_picture = 1;
				if (got_picture){
					//讀取到一幀視頻,處理解碼後視頻frame
					if (first_time){
						printf("\nCodec Full Name:%s\n", pCodecCtx->codec->long_name);
						printf("width:%d\nheight:%d\n\n", pCodecCtx->width, pCodecCtx->height);
						first_time = 0;
					}
					//Y, U, V
					int i;
					for (i = 0; i < pFrame->height; i++){
						fwrite(pFrame->data[0] + pFrame->linesize[0] * i, 1, pFrame->width, fp_out);
					}
					for (i = 0; i < pFrame->height / 2; i++){
						fwrite(pFrame->data[1] + pFrame->linesize[1] * i, 1, pFrame->width / 2, fp_out);
					}
					for (i = 0; i < pFrame->height / 2; i++){
						fwrite(pFrame->data[2] + pFrame->linesize[2] * i, 1, pFrame->width / 2, fp_out);
					}

					n_frame++;
					printf("Succeed to decode %d frame!\n", n_frame);
				}
			}
		}

	}

	//Flush Decoder
	packet.data = NULL;
	packet.size = 0;
	while (1){
		ret = avcodec_receive_frame(pCodecCtx, pFrame);
		if (ret < 0) {
			printf("Decode Error.\n");
			return ret;
		}
		if (!got_picture){
			break;
		}
		else {
			//Y, U, V
			int i;
			for (i = 0; i < pFrame->height; i++){
				fwrite(pFrame->data[0] + pFrame->linesize[0] * i, 1, pFrame->width, fp_out);
			}
			for (i = 0; i < pFrame->height / 2; i++){
				fwrite(pFrame->data[1] + pFrame->linesize[1] * i, 1, pFrame->width / 2, fp_out);
			}
			for (i = 0; i < pFrame->height / 2; i++){
				fwrite(pFrame->data[2] + pFrame->linesize[2] * i, 1, pFrame->width / 2, fp_out);
			}

			printf("Flush Decoder: Succeed to decode 1 frame!\n");
		}
	}

	fclose(fp_in);
	fclose(fp_out);


	//釋放AVFormatContext和它所有的流
	avformat_free_context(pFormatCtx);

	av_parser_close(pCodecParserCtx);


	av_frame_free(&pFrame);
	avcodec_close(pCodecCtx);
	av_free(pCodecCtx);

	return 0;
}


#include <iostream>
#include <fstream>
using namespace std;

int fill_iobuffer(void * opaque, uint8_t *buf, int bufsize){
// 	if (!feof(fp_open)){
// 		int true_size = fread(buf, 1, buf_size, fp_open);
// 		return true_size;
// 	}
// 	else{
// 		return -1;
// 	}

	static int flag = 0;
	if (flag == 0) {
		ifstream file;
		file.open("data\\x-key.264", ios::in | ios::binary);
		int count = file.read((char*)buf, bufsize).gcount();
		cout << "count is " << count << endl;
		file.close();
		flag = 1;
		return count;
	}
	else {
		return -1;
	}
}

int fun3(int argc, char* argv[])
{
	AVCodec *pCodec = NULL;

	const int in_buffer_size = 4096;
	uint8_t* in_buffer = new uint8_t[4096 + 460800];
	uint8_t *cur_ptr;
	int cur_size;
	int ret, i, got_picture;
	int y_size;
	AVFrame	*pFrame;     //AVFrame存儲一幀解碼後的像素數據
	AVPacket packet;    //存儲一幀(一般情況下)壓縮編碼數據

	enum AVCodecID codec_id = AV_CODEC_ID_H264;
	char filepath_in[] = "data\\net-download-test.264";
	char filepath_out[] = "data\\x-key.264.yuv";
	int first_time = 1;

	//註冊所有的編解碼器
	void *opaque = NULL;
	av_demuxer_iterate(&opaque);
	//av_register_all();  被棄用

	//打開多媒體文件
	AVFormatContext *pFormatCtx = NULL;
	//爲AVFormatContext分配內存
	pFormatCtx = avformat_alloc_context();


#if 1
	//////////////////////////////////////////////////////////////////////////
	AVFormatContext *ic = NULL;
	ic = avformat_alloc_context();
	int m_len = 1024 * 1024 * 3;
	unsigned char * iobuffer = (unsigned char *)av_malloc(m_len);
	AVIOContext *avio = avio_alloc_context(iobuffer, m_len, 0, NULL, fill_iobuffer, NULL, NULL);
	ic->pb = avio;
	if (avformat_open_input(&ic, "nothing", NULL, NULL) != 0){
		return -1;   // Couldn't open file
	}
	//////////////////////////////////////////////////////////////////////////
#else
	if (avformat_open_input(&pFormatCtx, filepath_in, NULL, NULL) != 0){
		return -1;   // Couldn't open file
	}
#endif
	//獨立的解碼上下文
	//AVCodecContext視頻解碼的上下文,爲AVCodecContext分配內存
	AVCodecContext *pCodecCtx = avcodec_alloc_context3(pCodec);
	if (!pCodecCtx){
		printf("Could not allocate video codec context\n");
		return -1;
	}

	//循環遍歷所有流,找到視頻流
	int videoStream = -1;
	for (i = 0; i < pFormatCtx->nb_streams; i++) {
		if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
			videoStream = i;
			break;
		}
	}

	//將配置參數複製到AVCodecContext中
	//avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStream]->codecpar);

	//查找視頻解碼器
	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
	if (!pCodec) {
		printf("Codec not found\n");
		return -1;
	}

	//打開解碼器
	if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
		printf("Could not open codec\n");
		return -1;
	}

	//初始化AVCodecParserContext
	AVCodecParserContext *pCodecParserCtx = NULL;
	pCodecParserCtx = av_parser_init(codec_id);
	if (!pCodecParserCtx){
		printf("Could not allocate video parser context\n");
		return -1;
	}

	//Input File
	FILE *fp_in = fopen(filepath_in, "rb");
	if (!fp_in) {
		printf("Could not open input stream\n");
		return -1;
	}

	//Output File
	FILE *fp_out = fopen(filepath_out, "wb");
	if (!fp_out) {
		printf("Could not open output YUV file\n");
		return -1;
	}

	//爲AVFrame分配內存
	pFrame = av_frame_alloc();
	//初始化AVPacket
	av_init_packet(&packet);

	int n_frame = 0;
	while (1) {
		cur_size = fread(in_buffer, 1, in_buffer_size, fp_in);
		if (cur_size == 0)
			break;
		cur_ptr = in_buffer;

		while (cur_size > 0){

			//解析獲得一個Packet
			int len = av_parser_parse2(
				pCodecParserCtx, pCodecCtx,
				&packet.data, &packet.size,
				cur_ptr, cur_size,
				AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);

			cur_ptr += len;
			cur_size -= len;

			if (packet.size == 0)
				continue;

			//Some Info from AVCodecParserContext
			printf("[Packet]Size:%6d\t", packet.size);
			switch (pCodecParserCtx->pict_type){
			case AV_PICTURE_TYPE_I: printf("Type:I\t"); break;
			case AV_PICTURE_TYPE_P: printf("Type:P\t"); break;
			case AV_PICTURE_TYPE_B: printf("Type:B\t"); break;
			default: printf("Type:Other\t"); break;
			}
			printf("Number:%4d\n", pCodecParserCtx->output_picture_number);

			//解碼一幀數據
			//avcodec_send_packet()向解碼器提供輸入AVPacket
			ret = avcodec_send_packet(pCodecCtx, &packet);
			if (ret != 0)
			{
				return -1;
			}
			//avcodec_receive_frame()接收解碼的幀AVFrame
			while (avcodec_receive_frame(pCodecCtx, pFrame) == 0)
			{
				got_picture = 1;
				if (got_picture){
					//讀取到一幀視頻,處理解碼後視頻frame
					if (first_time){
						printf("\nCodec Full Name:%s\n", pCodecCtx->codec->long_name);
						printf("width:%d\nheight:%d\n\n", pCodecCtx->width, pCodecCtx->height);
						first_time = 0;
					}
					//Y, U, V
					int i;
					for (i = 0; i < pFrame->height; i++){
						fwrite(pFrame->data[0] + pFrame->linesize[0] * i, 1, pFrame->width, fp_out);
					}
					for (i = 0; i < pFrame->height / 2; i++){
						fwrite(pFrame->data[1] + pFrame->linesize[1] * i, 1, pFrame->width / 2, fp_out);
					}
					for (i = 0; i < pFrame->height / 2; i++){
						fwrite(pFrame->data[2] + pFrame->linesize[2] * i, 1, pFrame->width / 2, fp_out);
					}

					n_frame++;
					printf("Succeed to decode %d frame!\n", n_frame);
				}
			}
		}

	}

	//Flush Decoder
	packet.data = NULL;
	packet.size = 0;
	while (1){
		ret = avcodec_receive_frame(pCodecCtx, pFrame);
		if (ret < 0) {
			printf("Decode Error.\n");
			return ret;
		}
		if (!got_picture){
			break;
		}
		else {
			//Y, U, V
			int i;
			for (i = 0; i < pFrame->height; i++){
				fwrite(pFrame->data[0] + pFrame->linesize[0] * i, 1, pFrame->width, fp_out);
			}
			for (i = 0; i < pFrame->height / 2; i++){
				fwrite(pFrame->data[1] + pFrame->linesize[1] * i, 1, pFrame->width / 2, fp_out);
			}
			for (i = 0; i < pFrame->height / 2; i++){
				fwrite(pFrame->data[2] + pFrame->linesize[2] * i, 1, pFrame->width / 2, fp_out);
			}

			printf("Flush Decoder: Succeed to decode 1 frame!\n");
		}
	}

	fclose(fp_in);
	fclose(fp_out);


	//釋放AVFormatContext和它所有的流
	avformat_free_context(pFormatCtx);

	av_parser_close(pCodecParserCtx);


	av_frame_free(&pFrame);
	avcodec_close(pCodecCtx);
	av_free(pCodecCtx);

	return 0;
}
//////////////////////////////////////////////////////////////////////////

#define INBUF_SIZE 4096

#include <fstream>
#include <iostream>

using namespace std;

int saveImgFile(char* _buf, int _len, char* _fileName)
{
	ofstream file;
	try {
		file.open(_fileName, ios::out | ios::binary);
	}
	catch (...) {
		cout << "open file failed." << endl;
		return -1;
	}

	if (!file.is_open()) {
		cout << "open file failed2." << endl;
		return -1;
	}

	file.write(_buf, _len);

	file.close();

	return 0;
}

static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, char *filename)
{
#if 1
	FILE *f;
	int i;

	f = fopen(filename, "w");
	fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
	for (i = 0; i < ysize; i++){
		fwrite(buf + i * wrap, 1, xsize, f);
	}
	
	fclose(f);
#else

	saveImgFile((char *)buf, xsize*ysize*1.5, filename);
#endif
}


static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt,
	const char *filename)
{
	char bufAutoName[1024];
	int ret;

	ret = avcodec_send_packet(dec_ctx, pkt);
	if (ret < 0) {
		fprintf(stderr, "Error sending a packet for decoding\n");
		exit(1);
	}

	int dstW = 80;
	int dstH = 80;
	SwsContext* m_pImgCtx = NULL;
	if (!m_pImgCtx){
		dstW = dec_ctx->width;
		dstH = dec_ctx->height;
		dstW = 80;
		dstH = 80;

		m_pImgCtx = sws_getContext(dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt, dstW, dstH, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
	}


	AVFrame *yuv = NULL;
	yuv = av_frame_alloc();
	int vsize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, dstW, dstH, 1);
	const uint8_t * tmpbuf = (uint8_t *)av_malloc(vsize);
	av_image_fill_arrays(yuv->data, yuv->linesize, tmpbuf, AV_PIX_FMT_YUV420P, dstW, dstH, 1);
	//sws_scale(m_pImgCtx, frame->data, frame->linesize, 0, frame->height, yuv->data, yuv->linesize);

	while (ret >= 0) {
		ret = avcodec_receive_frame(dec_ctx, frame);
		if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
			return;
		else if (ret < 0) {
			fprintf(stderr, "Error during decoding\n");
			exit(1);
		}
		_snprintf(bufAutoName, sizeof(bufAutoName), "%s-%d-%d_%d.yuv420p", filename, dec_ctx->frame_number, dstW, dstH);

		sws_scale(m_pImgCtx, frame->data, frame->linesize, 0, dec_ctx->height, yuv->data, yuv->linesize);


		int len = vsize;
		char* tmp = new char[len];
		memcpy(tmp, (unsigned char*)yuv->data[0], len);
		saveImgFile((char*)tmp, len, bufAutoName);
// 		exit(0);
// 
// 		printf("saving frame %3d\n", dec_ctx->frame_number);
// 		fflush(stdout);
// 
// 		/* the picture is allocated by the decoder. no need to free it */
// 		printf("frame->linesize[0]=%d, frame->width=%d, frame->height=%d\n", frame->linesize[0], frame->width, frame->height);
// 		pgm_save(frame->data[0], frame->linesize[0], frame->width, frame->height, bufAutoName);
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
// 	fun3(argc, argv);
// 	return 0;

	const char *filename, *outfilename;
	AVCodec *codec = NULL;
	AVCodecParserContext *parser;
	AVCodecContext *c = NULL;
	FILE *f;
	AVFrame *frame;
	//uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
	int inbuflien = 1024*1024*5;
	uint8_t* inbuf = new uint8_t[inbuflien];
	uint8_t *data;
	size_t   data_size;
	int ret;
	AVPacket *pkt;

	std::cout << "argv[1] " << argv[1] << std::endl;
	std::cout << "argv[2] " << argv[2] << std::endl;
	if (argc <= 2) {
		fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]);
		exit(0);
	}
	filename = argv[1];
	outfilename = argv[2];

	std::cout << "__LINE__ " << __LINE__ << std::endl;

	pkt = av_packet_alloc();
	if (!pkt)
		exit(1);

	std::cout << "__LINE__ " << __LINE__ << std::endl;

	/* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */
	//memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);
	memset(inbuf, 0, inbuflien);
	std::cout << "__LINE__ " << __LINE__ << std::endl;

	/* find the MPEG-1 video decoder AV_CODEC_ID_MPEG1VIDEO*/
	codec = avcodec_find_decoder(AV_CODEC_ID_H264);
	if (!codec) {
		fprintf(stderr, "Codec not found\n");
		exit(1);
	}

	std::cout << "__LINE__ " << __LINE__ << std::endl;

	parser = av_parser_init(codec->id);
	if (!parser) {
		fprintf(stderr, "parser not found\n");
		exit(1);
	}

	std::cout << "__LINE__ " << __LINE__ << std::endl;

	c = avcodec_alloc_context3(codec);
	if (!c) {
		fprintf(stderr, "Could not allocate video codec context\n");
		exit(1);
	}

	std::cout << "__LINE__ " << __LINE__ << std::endl;

	/* For some codecs, such as msmpeg4 and mpeg4, width and height
	MUST be initialized there because this information is not
	available in the bitstream. */

	/* open it */
	if (avcodec_open2(c, codec, NULL) < 0) {
		fprintf(stderr, "Could not open codec\n");
		exit(1);
	}

	std::cout << "__LINE__ " << __LINE__ << std::endl;

	f = fopen(filename, "rb");
	if (!f) {
		fprintf(stderr, "Could not open %s\n", filename);
		exit(1);
	}

	std::cout << "__LINE__ " << __LINE__ << std::endl;

	frame = av_frame_alloc();
	if (!frame) {
		fprintf(stderr, "Could not allocate video frame\n");
		exit(1);
	}
//	avpicture_get_size();
	//av_image_get_buffer_size();
	std::cout << "__LINE__ " << __LINE__ << std::endl;

	while (!feof(f)) {
		/* read raw data from the input file */
		data_size = fread(inbuf, 1, INBUF_SIZE, f);
		if (!data_size)
			break;

		/* use the parser to split the data into frames */
		data = inbuf;
		while (data_size > 0) {
			//avcodec_decode_video2
			ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size, data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
			if (ret < 0) {
				fprintf(stderr, "Error while parsing\n");
				exit(1);
			}
			data += ret;
			data_size -= ret;

#if 1
			if (pkt->size) {
				//std::cout << "pict_type " << (parser->pict_type == AV_PICTURE_TYPE_I ? " AV_PICTURE_TYPE_I " : " AV_PICTURE_TYPE_P ") << "----pix_fmt is " << c->pix_fmt << std::endl;

				decode(c, frame, pkt, outfilename);
			}
#else

#endif
		}
	}
	/* flush the decoder */
	decode(c, frame, NULL, outfilename);

	fclose(f);

	av_parser_close(parser);
	avcodec_free_context(&c);
	av_frame_free(&frame);
	av_packet_free(&pkt);
	cout << "over" << "\n";
	return 0;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章