aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c92
1 files changed, 86 insertions, 6 deletions
diff --git a/main.c b/main.c
index 03af7da..65ce2ba 100644
--- a/main.c
+++ b/main.c
@@ -113,7 +113,68 @@ static void cleanup(struct instance *i)
close(i->out.fd);
}
-static int save_encoded(struct instance *i, const void *buf, unsigned int size)
+//specific to VP8
+static void mem_put_le16(void *vmem, int val)
+{
+ uint8_t *mem = (uint8_t *)vmem;
+
+ mem[0] = (uint8_t)((val >> 0) & 0xff);
+ mem[1] = (uint8_t)((val >> 8) & 0xff);
+}
+
+static void mem_put_le32(void *vmem, int val)
+{
+ uint8_t *mem = (uint8_t *)vmem;
+
+ mem[0] = (uint8_t)((val >> 0) & 0xff);
+ mem[1] = (uint8_t)((val >> 8) & 0xff);
+ mem[2] = (uint8_t)((val >> 16) & 0xff);
+ mem[3] = (uint8_t)((val >> 24) & 0xff);
+}
+
+#define VP8_FOURCC 0x30385056
+#define VP9_FOURCC 0x30395056
+
+static void ivf_write_file_header(int outfile, off_t offset, unsigned int width,
+ unsigned int height, unsigned int fourcc,
+ int frame_cnt, int timebase_den,
+ int timebase_num)
+{
+ char header[32];
+
+ header[0] = 'D';
+ header[1] = 'K';
+ header[2] = 'I';
+ header[3] = 'F';
+ mem_put_le16(header + 4, 0); // version
+ mem_put_le16(header + 6, 32); // header size
+ mem_put_le32(header + 8, fourcc); // fourcc
+ mem_put_le16(header + 12, width); // width
+ mem_put_le16(header + 14, height); // height
+ mem_put_le32(header + 16, timebase_den); // rate
+ mem_put_le32(header + 20, timebase_num); // scale
+ mem_put_le32(header + 24, frame_cnt); // length
+ mem_put_le32(header + 28, 0); // unused
+
+ pwrite(outfile, header, 32, offset);
+}
+
+static void ivf_write_frame_header(int outfile, off_t offset, size_t frame_size)
+{
+ char header[12];
+ static int64_t pts = 0;
+
+ mem_put_le32(header, (int)frame_size);
+ mem_put_le32(header + 4, (int)(pts & 0xFFFFFFFF));
+ mem_put_le32(header + 8, (int)(pts >> 32));
+
+ pwrite(outfile, header, 12, offset);
+
+ pts++;
+}
+
+static int save_encoded(struct instance *i, const void *buf, unsigned int size,
+ bool is_ivf)
{
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
char filename[64];
@@ -125,7 +186,10 @@ static int save_encoded(struct instance *i, const void *buf, unsigned int size)
if (!i->save_encoded)
return 0;
- ret = sprintf(filename, "%s/encoded.%s", i->save_path, ext);
+ if (is_ivf)
+ ret = sprintf(filename, "%s/encoded.%s.ivf", i->save_path, ext);
+ else
+ ret = sprintf(filename, "%s/encoded.%s", i->save_path, ext);
if (ret < 0) {
err("sprintf fail (%s)", strerror(errno));
return -1;
@@ -142,7 +206,18 @@ static int save_encoded(struct instance *i, const void *buf, unsigned int size)
dbg("created file %s", filename);
+ if (is_ivf) {
+ ivf_write_file_header(out->fd, out->offs, i->width, i->height,
+ VP8_FOURCC, 0, 30, 1);
+ out->offs += 32;
+ }
write:
+ if (is_ivf) {
+ dbg("frame_header: %d, %d", out->offs, size);
+ ivf_write_frame_header(out->fd, out->offs, size);
+ out->offs += 12;
+ }
+
written = pwrite(out->fd, buf, size, out->offs);
if (written < 0) {
err("cannot write to file (%s)", strerror(errno));
@@ -250,13 +325,15 @@ static void *main_thread_func(void *args)
handle_v4l_events(vid);
if (revents & (POLLIN | POLLRDNORM)) {
- unsigned int bytesused;
+ unsigned int bytesused, dataoffset;
/* capture buffer is ready */
dbg("dequeuing capture buffer");
- ret = video_dequeue_capture(i, &n, &finished, &bytesused);
+ ret = video_dequeue_capture(i, &n, &finished,
+ &bytesused, &dataoffset,
+ NULL);
if (ret < 0)
goto next_event;
@@ -272,8 +349,11 @@ static void *main_thread_func(void *args)
vid->total_encoded++;
- save_encoded(i, (const void *)vid->cap_buf_addr[n][0],
- bytesused);
+ uint8_t *data = (uint8_t*)vid->cap_buf_addr[n][0];
+ data += dataoffset;
+
+ save_encoded(i, (const void *)data, bytesused,
+ i->codec == V4L2_PIX_FMT_VP8);
ret = video_queue_buf_cap(i, n);
if (!ret) {