Skip to content

Instantly share code, notes, and snippets.

@rrva

rrva/decode.c Secret

Created April 1, 2016 18:46
Show Gist options
  • Save rrva/471a0f106f67e380ca76ce3759b33a18 to your computer and use it in GitHub Desktop.
Save rrva/471a0f106f67e380ca76ce3759b33a18 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
static AVFormatContext *inctx, *outctx;
#define MAX_STREAMS 16
static AVCodecContext *inavctx[MAX_STREAMS];
static AVCodecContext *outavctx[MAX_STREAMS];
static int openInputFile(const char *file) {
int res;
inctx = NULL;
res = avformat_open_input(&inctx, file, NULL, NULL);
if (res != 0)
return res;
res = avformat_find_stream_info(inctx, NULL);
if (res < 0)
return res;
return 0;
}
static void closeInputFile(void) {
int n;
for (n = 0; n < inctx->nb_streams; n++)
if (inavctx[n]) {
avcodec_close(inavctx[n]);
//avcodec_free_context(&inavctx[n]);
}
avformat_close_input(&inctx);
}
int main(int argc, char *argv[]) {
char *input = argv[1];
char *output = argv[2];
int res;
printf("Converting %s to %s\n", input, output);
av_register_all();
if ((res = openInputFile(input)) < 0) {
fprintf(stderr, "Failed to open input file %s\n", input);
return res;
}
AVFrame *frame = av_frame_alloc();
AVPacket pkt;
int videoStreamIndex = -1;
for (int i = 0; i < inctx->nb_streams; i++) {
AVStream *inst = inctx->streams[i];
AVCodecContext *inc = inst->codec;
if (inctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStreamIndex = i;
inavctx[i] = avcodec_alloc_context3(inc->codec);
avcodec_copy_context(inavctx[i], inc);
if ((res = avcodec_open2(inavctx[i], avcodec_find_decoder(inc->codec_id), NULL)) < 0)
return res;
break;
}
}
if (videoStreamIndex == -1) {
printf("Could not find video stream\n");
return -1;
}
av_init_packet(&pkt);
uint64_t frameCount = 0;
int keyFrame = 0;
uint64_t lastIFramePos = 0;
uint64_t lastIFramePts = 0;
uint64_t lastIFrameCount = 0;
uint64_t packetCount = 0;
int frameFinished = 0;
int codedPictureNumber = -1;
int displayPictureNumber = -1;
char pict_type;
while (av_read_frame(inctx, &pkt) >= 0) {
packetCount++;
if (pkt.flags & AV_PKT_FLAG_CORRUPT) {
printf("Corrupt packet detected! pos=%lu\n", pkt.pos);
}
if (pkt.stream_index == videoStreamIndex) {
keyFrame = pkt.flags & AV_PKT_FLAG_KEY;
res = avcodec_decode_video2(inavctx[videoStreamIndex],frame,&frameFinished,&pkt);
if(frameFinished == 1) {
frameCount++;
codedPictureNumber = frame->coded_picture_number;
displayPictureNumber = frame->display_picture_number;
pict_type = av_get_picture_type_char(frame->pict_type);
if(frame->key_frame != keyFrame) {
printf("DIFF frame=%lu key_frame=%d frame->key_frame=%d pict_type=%c byte_pos=%lu pts=%lu packet=%lu poc=%d\n", frameCount,
keyFrame, frame->key_frame, pict_type, pkt.pos, pkt.pts, packetCount, codedPictureNumber);
}
} else {
//pict_type = ' ';
//codedPictureNumber = 0;
//displayPictureNumber = 0;
}
if(res == -1) {
printf("Failed to decode video frame\n");
return -1;
}
if (keyFrame == 1) {
lastIFramePos = pkt.pos;
lastIFramePts = pkt.pts;
lastIFrameCount = frameCount;
} else {
if (pkt.pos > lastIFramePos && pkt.pts < lastIFramePts) {
printf("Open GOP detected! frame=%lu pos=%lu > "
"iframe_pos=%lu but "
"pts=%lu < iframe_pts=%lu\n",
frameCount, pkt.pos, lastIFramePos, pkt.pts,
lastIFramePts);
}
}
printf("frame=%lu key_frame=%d pict_type=%c byte_pos=%lu pts=%lu packet=%lu poc=%d doc=%d\n", frameCount,
keyFrame, pict_type, pkt.pos, pkt.pts, packetCount, codedPictureNumber, displayPictureNumber);
}
}
av_free_packet(&pkt);
closeInputFile();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment