streamers / out-stream-avf.c @ 9cc07b6c
History | View | Annotate | Download (3.07 KB)
1 |
/*
|
---|---|
2 |
* Copyright (c) 2010 Luca Abeni
|
3 |
*
|
4 |
* This is free software; see gpl-3.0.txt
|
5 |
*/
|
6 |
|
7 |
#include <libavformat/avformat.h> |
8 |
#include <stdio.h> |
9 |
|
10 |
#include "out-stream.h" |
11 |
#include "dbg.h" |
12 |
|
13 |
static const char *output_format = "nut"; |
14 |
static const char *output_file = "out.nut"; |
15 |
|
16 |
static enum CodecID libav_codec_id(uint8_t mytype) |
17 |
{ |
18 |
switch (mytype) {
|
19 |
case 1: |
20 |
return CODEC_ID_MPEG2VIDEO;
|
21 |
case 2: |
22 |
return CODEC_ID_H261;
|
23 |
case 3: |
24 |
return CODEC_ID_H263P;
|
25 |
case 4: |
26 |
return CODEC_ID_MJPEG;
|
27 |
case 5: |
28 |
return CODEC_ID_MPEG4;
|
29 |
case 6: |
30 |
return CODEC_ID_FLV1;
|
31 |
case 7: |
32 |
return CODEC_ID_SVQ3;
|
33 |
case 8: |
34 |
return CODEC_ID_DVVIDEO;
|
35 |
case 9: |
36 |
return CODEC_ID_H264;
|
37 |
case 10: |
38 |
return CODEC_ID_THEORA;
|
39 |
case 11: |
40 |
return CODEC_ID_SNOW;
|
41 |
case 12: |
42 |
return CODEC_ID_VP6;
|
43 |
case 13: |
44 |
return CODEC_ID_DIRAC;
|
45 |
default:
|
46 |
fprintf(stderr, "Unknown codec %d\n", mytype);
|
47 |
return 0; |
48 |
} |
49 |
} |
50 |
|
51 |
static AVFormatContext *format_init(const uint8_t *data) |
52 |
{ |
53 |
AVFormatContext *of; |
54 |
AVCodecContext *c; |
55 |
AVOutputFormat *outfmt; |
56 |
int width, height, frame_rate_n, frame_rate_d;
|
57 |
|
58 |
av_register_all(); |
59 |
|
60 |
width = data[1] << 8 | data[2]; |
61 |
height = data[3] << 8 | data[4]; |
62 |
frame_rate_n = data[5] << 8 | data[6]; |
63 |
frame_rate_d = data[7] << 8 | data[8]; |
64 |
dprintf("Frame size: %dx%d -- Frame rate: %d / %d\n", width, height, frame_rate_n, frame_rate_d);
|
65 |
|
66 |
outfmt = av_guess_format(output_format, NULL, NULL); |
67 |
of = avformat_alloc_context(); |
68 |
if (of == NULL) { |
69 |
return NULL; |
70 |
} |
71 |
of->oformat = outfmt; |
72 |
av_new_stream(of, 0);
|
73 |
c = of->streams[0]->codec;
|
74 |
c->codec_id = libav_codec_id(data[0]);
|
75 |
c->codec_type = CODEC_TYPE_VIDEO; |
76 |
c->width = width; |
77 |
c->height= height; |
78 |
c->time_base.den = frame_rate_n; |
79 |
c->time_base.num = frame_rate_d; |
80 |
of->streams[0]->avg_frame_rate.num = frame_rate_n;
|
81 |
of->streams[0]->avg_frame_rate.den = frame_rate_d;
|
82 |
c->pix_fmt = PIX_FMT_YUV420P; |
83 |
|
84 |
return of;
|
85 |
} |
86 |
|
87 |
void chunk_write(int id, const uint8_t *data, int size) |
88 |
{ |
89 |
static AVFormatContext *outctx;
|
90 |
const int header_size = 1 + 2 + 2 + 2 + 2 + 1; // 1 Frame type + 2 width + 2 height + 2 frame rate num + 2 frame rate den + 1 number of frames |
91 |
int frames, i;
|
92 |
|
93 |
if (data[0] > 127) { |
94 |
fprintf(stderr, "Error! Non video chunk: %x!!!\n", data[0]); |
95 |
return;
|
96 |
} |
97 |
if (outctx == NULL) { |
98 |
outctx = format_init(data); |
99 |
if (outctx == NULL) { |
100 |
fprintf(stderr, "Format init failed\n");
|
101 |
|
102 |
return;
|
103 |
} |
104 |
av_set_parameters(outctx, NULL);
|
105 |
snprintf(outctx->filename, sizeof(outctx->filename), "%s", output_file); |
106 |
dump_format(outctx, 0, output_file, 1); |
107 |
url_fopen(&outctx->pb, output_file, URL_WRONLY); |
108 |
av_write_header(outctx); |
109 |
} |
110 |
|
111 |
frames = data[9];
|
112 |
for (i = 0; i < frames; i++) { |
113 |
AVPacket pkt; |
114 |
|
115 |
dprintf("Frame %d has size %d\n", i, data[10 + 2 * i] << 8 | data[11 + 2 * i]); |
116 |
av_init_packet(&pkt); |
117 |
pkt.stream_index = 0; // FIXME! |
118 |
pkt.pts = AV_NOPTS_VALUE; // FIXME!
|
119 |
pkt.data = data + header_size + frames * 2;
|
120 |
pkt.size = data[10 + 2 * i] << 8 | data[11 + 2 * i]; |
121 |
av_interleaved_write_frame(outctx, &pkt); |
122 |
} |
123 |
} |