// 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;
}