Skip to content

Instantly share code, notes, and snippets.

@Milek7

Milek7/stkok.c Secret

Created July 12, 2021 15:20
// gcc -o video video.c -lavcodec -lavformat -lavutil -lavdevice -pthread
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <threads.h>
#include <unistd.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include <libavutil/pixdesc.h>
int av_die(const char* info1, const char* info2, const char* msg, int err)
{
char buffer[256];
av_strerror(err, buffer, sizeof buffer);
printf("%s, %s, %s, %s", info1, info2, msg, buffer);
exit(1);
return 0;
}
int M_ERC;
#define M_XSTR(s) M_STR(s)
#define M_STR(s) #s
#define AV_TRY(x) ((M_ERC = (x)) < 0 ? av_die(M_XSTR(__LINE__), __FILE__, #x, M_ERC) : M_ERC)
mtx_t video_lock;
void *video_data;
int main(int argc, char *argv[])
{
mtx_init(&video_lock, mtx_plain);
avdevice_register_all();
AVInputFormat *input_format = av_find_input_format("video4linux2");
assert(input_format);
AVFormatContext *ctx = avformat_alloc_context();
ctx->flags = AVFMT_FLAG_NONBLOCK;
AV_TRY(avformat_open_input(&ctx, "/dev/video0", input_format, NULL));
assert(ctx);
AVCodec *codec = NULL;
AVStream *stream = NULL;
int stream_index = AV_TRY(av_find_best_stream(ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0));
assert(codec);
stream = ctx->streams[stream_index];
assert(stream);
AVCodecContext *codec_ctx = NULL;
codec_ctx = avcodec_alloc_context3(codec);
assert(codec_ctx);
AV_TRY(avcodec_parameters_to_context(codec_ctx, stream->codecpar));
AVDictionary *codec_opts = NULL;
av_dict_set(&codec_opts, "refcounted_frames", "1", 0);
assert(codec_opts);
AV_TRY(avcodec_open2(codec_ctx, codec, &codec_opts));
assert(!av_dict_count(codec_opts));
AVFrame *frame = av_frame_alloc();
AVPacket *packet = av_packet_alloc();
int ret;
while (1)
{
while ((ret = avcodec_receive_frame(codec_ctx, frame)) == 0)
{
assert(frame->width == 720);
assert(frame->height == 480);
assert(frame->format == AV_PIX_FMT_UYVY422);
mtx_lock(&video_lock);
if (!video_data)
free(video_data);
video_data = malloc(frame->linesize[0] * frame->height);
memcpy(video_data, frame->data[0], frame->linesize[0] * frame->height);
mtx_unlock(&video_lock);
av_frame_unref(frame);
}
if (ret == AVERROR(EAGAIN))
{
while (1)
{
ret = av_read_frame(ctx, packet);
if (ret != 0)
break;
if (packet->stream_index == stream_index)
break;
av_packet_unref(packet);
}
if (ret == AVERROR(EAGAIN)) {
usleep(500);
continue;
}
if (ret != 0) {
printf("failed to receive frame\n");
continue;
}
ret = avcodec_send_packet(codec_ctx, packet);
if (ret != 0)
printf("decoding error\n");
av_packet_unref(packet);
}
else if (ret == AVERROR_EOF)
{
break;
}
else
{
av_die("decoding error", "", "avcodec_receive_frame", ret);
}
}
if (!video_data)
free(video_data);
av_frame_free(&frame);
av_packet_free(&packet);
avcodec_free_context(&codec_ctx);
avformat_close_input(&ctx);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment