Statistics
| Branch: | Revision:

streamers / out-stream-avf.c @ 69ae8acb

History | View | Annotate | Download (4 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
#include "payload.h"
13

    
14
static const char *output_format = "nut";
15
static const char *output_file = "/dev/stdout";
16

    
17
static int64_t prev_pts, prev_dts;
18

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

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

    
62
  av_register_all();
63

    
64
  payload_header_parse(data, &codec, &width, &height, &frame_rate_n, &frame_rate_d);
65
  dprintf("Frame size: %dx%d -- Frame rate: %d / %d\n", width, height, frame_rate_n, frame_rate_d);
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(codec);
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
  prev_pts = 0;
85
  prev_dts = 0;
86

    
87
  return of;
88
}
89

    
90
void chunk_write(int id, const uint8_t *data, int size)
91
{
92
  static AVFormatContext *outctx;
93
  const int header_size = VIDEO_PAYLOAD_HEADER_SIZE; 
94
  int frames, i;
95
  const uint8_t *p;
96

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

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

    
115
  frames = data[header_size - 1];
116
  p = data + header_size + FRAME_HEADER_SIZE * frames;
117
  for (i = 0; i < frames; i++) {
118
    AVPacket pkt;
119
    int32_t pts, dts;
120
    int frame_size;
121

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