Statistics
| Branch: | Revision:

streamers / out-stream-avf.c @ 7a86f98f

History | View | Annotate | Download (4.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 = "/dev/stdout";
15

    
16
static int64_t prev_pts, prev_dts;
17

    
18
static enum CodecID libav_codec_id(uint8_t mytype)
19
{
20
  switch (mytype) {
21
    case 1:
22
      return CODEC_ID_MPEG2VIDEO;
23
    case 2:
24
      return CODEC_ID_H261;
25
    case 3:
26
      return CODEC_ID_H263P;
27
    case 4:
28
      return CODEC_ID_MJPEG;
29
    case 5:
30
      return CODEC_ID_MPEG4;
31
    case 6:
32
      return CODEC_ID_FLV1;
33
    case 7:
34
      return CODEC_ID_SVQ3;
35
    case 8:
36
      return CODEC_ID_DVVIDEO;
37
    case 9:
38
      return CODEC_ID_H264;
39
    case 10:
40
      return CODEC_ID_THEORA;
41
    case 11:
42
      return CODEC_ID_SNOW;
43
    case 12:
44
      return CODEC_ID_VP6;
45
    case 13:
46
      return CODEC_ID_DIRAC;
47
    default:
48
      fprintf(stderr, "Unknown codec %d\n", mytype);
49
      return 0;
50
  }
51
}
52

    
53
static AVFormatContext *format_init(const uint8_t *data)
54
{
55
  AVFormatContext *of;
56
  AVCodecContext *c;
57
  AVOutputFormat *outfmt;
58
  int width, height, frame_rate_n, frame_rate_d;
59

    
60
  av_register_all();
61

    
62
  width = data[1] << 8 | data[2];
63
  height = data[3] << 8 | data[4];
64
  frame_rate_n = data[5] << 8 | data[6];
65
  frame_rate_d = data[7] << 8 | data[8];
66
  dprintf("Frame size: %dx%d -- Frame rate: %d / %d\n", width, height, frame_rate_n, frame_rate_d);
67

    
68
  outfmt = av_guess_format(output_format, NULL, NULL);
69
  of = avformat_alloc_context();
70
  if (of == NULL) {
71
    return NULL;
72
  }
73
  of->oformat = outfmt;
74
  av_new_stream(of, 0);
75
  c = of->streams[0]->codec;
76
  c->codec_id = libav_codec_id(data[0]);
77
  c->codec_type = CODEC_TYPE_VIDEO;
78
  c->width = width;
79
  c->height= height;
80
  c->time_base.den = frame_rate_n;
81
  c->time_base.num = frame_rate_d;
82
  of->streams[0]->avg_frame_rate.num = frame_rate_n;
83
  of->streams[0]->avg_frame_rate.den = frame_rate_d;
84
  c->pix_fmt = PIX_FMT_YUV420P;
85

    
86
  prev_pts = 0;
87
  prev_dts = 0;
88

    
89
  return of;
90
}
91

    
92
void chunk_write(int id, const uint8_t *data, int size)
93
{
94
  static AVFormatContext *outctx;
95
  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
96
  int frames, i;
97

    
98
  if (data[0] > 127) {
99
    fprintf(stderr, "Error! Non video chunk: %x!!!\n", data[0]);
100
    return;
101
  }
102
  if (outctx == NULL) {
103
    outctx = format_init(data);
104
    if (outctx == NULL) {
105
      fprintf(stderr, "Format init failed\n");
106

    
107
      return;
108
    }
109
    av_set_parameters(outctx, NULL);
110
    snprintf(outctx->filename, sizeof(outctx->filename), "%s", output_file);
111
    dump_format(outctx, 0, output_file, 1);
112
    url_fopen(&outctx->pb, output_file, URL_WRONLY);
113
    av_write_header(outctx);
114
  }
115

    
116
  frames = data[9];
117
  for (i = 0; i < frames; i++) {
118
    AVPacket pkt;
119
    int32_t pts, dts;
120
    int frame_size;
121

    
122
    frame_size = data[10 + (2 + 2 + 2) * i] << 8 | data[11 + (2 + 2 + 2) * i];
123
    pts = data[12 + (2 + 2 + 2) * i] << 8 | data[13 + (2 + 2 + 2) * i];
124
    dprintf("Frame %d PTS1: %d\n", i, pts);
125
    pts += (pts < prev_pts - (1 << 15)) ? ((prev_pts >> 16) + 1) << 16 : (prev_pts >> 16) << 16;
126
    dprintf(" PTS2: %d\n", pts);
127
    prev_pts = pts;
128
    dts = data[14 + (2 + 2 + 2) * i] << 8 | data[15 + (2 + 2 + 2) * i];
129
    dts += (dts < prev_dts - (1 << 15)) ? ((prev_dts >> 16) + 1) << 16 : (prev_dts >> 16) << 16;
130
    prev_dts = dts;
131
    dprintf("Frame %d has size %d --- PTS: %lld DTS: %lld\n", i, frame_size,
132
                                             av_rescale_q(pts, outctx->streams[0]->codec->time_base, AV_TIME_BASE_Q),
133
                                             av_rescale_q(dts, outctx->streams[0]->codec->time_base, AV_TIME_BASE_Q));
134
    av_init_packet(&pkt);
135
    pkt.stream_index = 0;        // FIXME!
136
    pkt.pts = av_rescale_q(pts, outctx->streams[0]->codec->time_base, outctx->streams[0]->time_base);
137
    pkt.dts = av_rescale_q(dts, outctx->streams[0]->codec->time_base, outctx->streams[0]->time_base);
138
    pkt.data = data + header_size + (i + 1) * (2 + 2 + 2);
139
    pkt.size = frame_size;
140
    av_interleaved_write_frame(outctx, &pkt);
141
  }
142
}