Code: Select all
#include "bcm_host.h"
#include "interface/mmal/mmal.h"
#include "interface/mmal/util/mmal_default_components.h"
#include "interface/mmal/util/mmal_util_params.h"
#include "interface/vcos/vcos.h"
#include <stdio.h>
#include <fcntl.h>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/motion_vector.h>
#include <libavutil/imgutils.h>
#include <libavformat/avformat.h>
#include "libswscale/swscale.h"
#include <libavutil/frame.h>
#include "libavformat/avformat.h"
#include <libswscale/swscale.h>
}
//FUNCTIONS
#define CHECK_STATUS(status, msg) if (status != MMAL_SUCCESS) { fprintf(stderr, msg"\n"); }
struct CONTEXT_T {
//VCOS_SEMAPHORE_T semaphore;
MMAL_QUEUE_T *queue=NULL;
MMAL_STATUS_T status;
} context;
MMAL_STATUS_T status = MMAL_EINVAL;
MMAL_COMPONENT_T *decoder = NULL;
MMAL_POOL_T *pool_in = NULL, *pool_out = NULL;
MMAL_PORT_T *input_port=NULL;
MMAL_PORT_T *output_port=NULL;
AVDictionary *opts = NULL;
int ret;
AVStream *st;
const char *src_filename = NULL;
AVFormatContext *fmt_ctx = NULL;
AVCodecContext *video_dec_ctx = NULL;
AVStream *video_stream = NULL;
AVCodec *dec = NULL;
AVCodecContext *dec_ctx = NULL;
int video_stream_idx = -1;
AVFrame *frame = NULL;
AVPacket pkt;
/** Callback from the control port.
* Component is sending us an event. */
void control_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
struct CONTEXT_T *ctx = (struct CONTEXT_T *)port->userdata;
fprintf(stderr,"CONTROL callback called\n");
switch (buffer->cmd)
{
case MMAL_EVENT_EOS:
/* Only sink component generate EOS events */
fprintf(stderr,"EOS\n");
break;
case MMAL_EVENT_ERROR:
/* Something went wrong. Signal this to the application */
ctx->status = *(MMAL_STATUS_T *)buffer->data;
fprintf(stderr,"ERROR: %d\n", ctx->status);
break;
default:
break;
}
/* Done with the event, recycle it */
mmal_buffer_header_release(buffer);
/* Kick the processing thread */
//vcos_semaphore_post(&ctx->semaphore);
}
void input_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
//struct CONTEXT_T *ctx = (struct CONTEXT_T *)port->userdata;
fprintf(stderr,"INPUT callback called\n");
/* The encoder is done with the data, just recycle the buffer header into its pool */
mmal_buffer_header_release(buffer);
}
/** Callback from the output port.
* Buffer has been produced by the port and is available for processing. */
void output_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer )
{
struct CONTEXT_T *ctx = (struct CONTEXT_T *)port->userdata;
fprintf(stderr,"OUTPUT callback called\n");
/* Queue the decoded video frame */
mmal_queue_put(ctx->queue, buffer);
}
uint8_t ffmpeg_camera_initialize(){
avformat_network_init();
av_register_all();
ret = avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) ;
if (ret <0 ) {
fprintf(stderr, "Could not open source %s\n", src_filename);
return ret;
}
ret = avformat_find_stream_info(fmt_ctx, NULL);
if (ret < 0) {
fprintf(stderr, "Could not find stream information\n");
return ret;
}
ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0); //1 this version creates dec
if (ret < 0) {
fprintf(stderr, "Could not find %s stream in input file '%s'\n",
av_get_media_type_string(AVMEDIA_TYPE_VIDEO), src_filename);
return ret;
} else {
int stream_idx = ret;
st = fmt_ctx->streams[stream_idx];
dec_ctx = avcodec_alloc_context3(NULL);
if (!dec_ctx) {
fprintf(stderr, "Failed to allocate codec\n");
return AVERROR(EINVAL);
}
ret = avcodec_parameters_to_context(dec_ctx, st->codecpar);
if (ret < 0) {
fprintf(stderr, "Failed to copy codec parameters to codec context\n");
return ret;
}
video_stream_idx = stream_idx;
video_stream = fmt_ctx->streams[video_stream_idx];
video_dec_ctx = dec_ctx;
av_dump_format(fmt_ctx, 0, src_filename, 0);
if (!video_stream) {
fprintf(stderr, "Could not find video stream in the input, aborting\n");
ret = 1;
}
}
return ret;
};
uint8_t run(AVPacket *packet)
{
MMAL_BUFFER_HEADER_T *buffer;
if (input_port) {
if ((buffer = mmal_queue_get(pool_in->queue)) != NULL)
{
mmal_buffer_header_mem_lock(buffer);
memcpy(buffer->data,packet->data,packet->size);
buffer->length=packet->size;
uint8_t nal_type=buffer->data[4] & 0x1f;
fprintf(stderr,"NAL TYPE --------------------> %d\n",nal_type);
//PRINT THE BUFFER CONTENTS
for (uint32_t i = 0; i < buffer->length; ++i) {
fprintf(stderr, "\\%02x", (unsigned char)buffer->data[i]);
}
fprintf(stderr,"\n");
//buffer->pts=packet->pts;
//buffer->dts=packet->pts;
buffer->pts = buffer->dts = MMAL_TIME_UNKNOWN;
mmal_buffer_header_mem_unlock(buffer);
fprintf(stderr, "%s sending packet >>>>> %i bytes\n", decoder->input[0]->name, (int)buffer->length);
status = mmal_port_send_buffer(decoder->input[0], buffer);
CHECK_STATUS(status, "failed to send buffer to input port");
}
}
if (output_port) {
while ((buffer = mmal_queue_get(context.queue)) != NULL)
{
mmal_buffer_header_mem_lock(buffer);
fprintf(stderr, "%s receiving %d bytes <<<<< frame\n", decoder->output[0]->name, buffer->length);
mmal_buffer_header_mem_unlock(buffer);
mmal_buffer_header_release(buffer);
}
while ((buffer = mmal_queue_get(pool_out->queue)) != NULL)
{
status = mmal_port_send_buffer(decoder->output[0], buffer);
CHECK_STATUS(status, "failed to send buffer to output port");
}
}
return status;
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s rtsp://<user>:<pass>@url\n", argv[0]);
return 1;
}
src_filename=argv[1];
//Initialize ffmpeg
ffmpeg_camera_initialize();
uint16_t iwidth=video_dec_ctx->width;
uint16_t iheight=video_dec_ctx->height;
status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &decoder);
CHECK_STATUS(status, "failed to create decoder");
// CONTROL PORT SETTINGS
decoder->control->userdata = (MMAL_PORT_USERDATA_T *)&context;
status = mmal_port_enable(decoder->control, control_callback);
CHECK_STATUS(status, "failed to enable control port");
//INPUT PORT SETTINGS
input_port=decoder->input[0];
MMAL_ES_FORMAT_T *format_in = decoder->input[0]->format;
format_in->type = MMAL_ES_TYPE_VIDEO;
format_in->encoding = MMAL_ENCODING_H264;
format_in->es->video.width = VCOS_ALIGN_UP(iwidth, 32);
format_in->es->video.height = VCOS_ALIGN_UP(iheight,16);
format_in->es->video.frame_rate.num = 30;
format_in->es->video.frame_rate.den = 1;
format_in->es->video.par.num = 1;
format_in->es->video.par.den = 1;
format_in->es->video.crop.width = iwidth;
format_in->es->video.crop.height = iheight;
//ALLOCATE Extradata, copying from avcodec context
status = mmal_format_extradata_alloc(format_in, video_dec_ctx->extradata_size);
fprintf(stderr,"FORMAT pack size %d\n", video_dec_ctx->extradata_size);
format_in->extradata_size = video_dec_ctx->extradata_size;
if (format_in->extradata_size)
memcpy(format_in->extradata, video_dec_ctx->extradata, video_dec_ctx->extradata_size);
//PRINT the contents of extradata
fprintf(stderr,"Extradata\n");
for (size_t i = 0; i != format_in->extradata_size+1; ++i) {
fprintf(stderr, "\\%02x", (unsigned char)format_in->extradata[i]);
}
fprintf(stderr,"\n");
/* Display the input port format */
fprintf(stderr,"---------------------------------------------------\n");
fprintf(stderr, "INPUT %s\n", decoder->input[0]->name);
fprintf(stderr, " type: %i, fourcc: %4.4s\n", format_in->type, (char *)&format_in->encoding);
fprintf(stderr, " bitrate: %i, framed: %i\n", format_in->bitrate,
!!(format_in->flags & MMAL_ES_FORMAT_FLAG_FRAMED));
fprintf(stderr, " extra data: %i, %p\n", format_in->extradata_size, format_in->extradata);
fprintf(stderr, " width: %i, height: %i, (%i,%i,%i,%i)\n",
format_in->es->video.width, format_in->es->video.height,
format_in->es->video.crop.x, format_in->es->video.crop.y,
format_in->es->video.crop.width, format_in->es->video.crop.height);
MMAL_PARAMETER_BOOLEAN_T error_concealment;
error_concealment.hdr.id = MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT;
error_concealment.hdr.size = sizeof(MMAL_PARAMETER_BOOLEAN_T);
error_concealment.enable = MMAL_FALSE;
status = mmal_port_parameter_set(decoder->input[0], &error_concealment.hdr);
CHECK_STATUS(status, "failed to set error concealment");
status = mmal_port_format_commit(decoder->input[0]);
CHECK_STATUS(status, "failed to commit input format");
status = mmal_port_enable(decoder->input[0], input_callback);
CHECK_STATUS(status, "failed to enable input port");
decoder->input[0]->buffer_num = decoder->input[0]->buffer_num_recommended;
decoder->input[0]->buffer_size = decoder->input[0]->buffer_size_recommended;
pool_in = mmal_pool_create(decoder->input[0]->buffer_num,
decoder->input[0]->buffer_size);
// Store a reference to our context in each port (will be used during callbacks) */
decoder->input[0]->userdata = (MMAL_PORT_USERDATA_T *)&context;
//OUTPUT PORT SETTINGS
MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format;
output_port=decoder->output[0];
format_out->type = MMAL_ES_TYPE_VIDEO;
format_out->encoding = MMAL_ENCODING_I420;
format_out->es->video.width = VCOS_ALIGN_UP(iwidth, 32);
format_out->es->video.height = VCOS_ALIGN_UP(iheight,16);
format_out->es->video.frame_rate.num = 30;
format_out->es->video.frame_rate.den = 1;
format_out->es->video.par.num = 0;
format_out->es->video.par.den = 1;
format_out->es->video.crop.width = iwidth;
format_out->es->video.crop.height = iheight;
/* Display the output port format */
fprintf(stderr,"---------------------------------------------------\n");
fprintf(stderr, "OUTPUT %s\n", decoder->output[0]->name);
fprintf(stderr, " type: %i, fourcc: %4.4s\n", format_out->type, (char *)&format_out->encoding);
fprintf(stderr, " bitrate: %i, framed: %i\n", format_out->bitrate,
!!(format_out->flags & MMAL_ES_FORMAT_FLAG_FRAMED));
fprintf(stderr, " extra data: %i, %p\n", format_out->extradata_size, format_out->extradata);
fprintf(stderr, " width: %i, height: %i, (%i,%i,%i,%i)\n",
format_out->es->video.width, format_out->es->video.height,
format_out->es->video.crop.x, format_out->es->video.crop.y,
format_out->es->video.crop.width, format_out->es->video.crop.height);
status = mmal_port_format_commit(decoder->output[0]);
CHECK_STATUS(status, "failed to commit output format");
status = mmal_port_enable(decoder->output[0], output_callback);
CHECK_STATUS(status, "failed to enable output port");
context.queue = mmal_queue_create();
decoder->output[0]->buffer_num = decoder->output[0]->buffer_num_recommended;
decoder->output[0]->buffer_size = decoder->output[0]->buffer_size_recommended;
pool_out = mmal_pool_create(decoder->output[0]->buffer_num,
decoder->output[0]->buffer_size);
decoder->output[0]->userdata = (MMAL_PORT_USERDATA_T *)&context;
fprintf(stderr,"Press Enter to Continue\n");
fprintf(stderr,"Press Enter again to stop\n");
getchar();
/* Start decoding */
fprintf(stderr, "start decoding\n");
int framecount=0;
char c;
int n, tem;
tem = fcntl(0, F_GETFL, 0);
fcntl (0, F_SETFL, (tem | O_NDELAY));
av_init_packet(&pkt);
//Loop
while (av_read_frame(fmt_ctx, &pkt) >= 0) {
if (pkt.stream_index == video_stream_idx) {
run(&pkt);
av_packet_unref(&pkt);
}
framecount++;
fprintf(stderr, "Frame number %d\n",framecount);
n = read(0, &c, 1);
if (n > 0) break;
}
fcntl(0, F_SETFL, tem);
/* End decoding */
fprintf(stderr, "end decoding\n");
avformat_network_deinit();
if (video_dec_ctx)
avcodec_free_context(&video_dec_ctx);
if (fmt_ctx)
avformat_close_input(&fmt_ctx);
mmal_port_disable(decoder->input[0]);
mmal_port_disable(decoder->output[0]);
mmal_port_disable(decoder->control);
mmal_port_flush(decoder->input[0]);
mmal_port_flush(decoder->output[0]);
mmal_port_flush(decoder->control);
if (decoder)
mmal_component_destroy(decoder);
if (pool_in)
mmal_pool_destroy(pool_in);
if (pool_out)
mmal_pool_destroy(pool_out);
if (context.queue)
mmal_queue_destroy(context.queue);
}
Code: Select all
Input #0, rtsp, from 'rtsp://01432721:admin:password@192.168.0.26/onvif2':
Metadata:
title : H.264 Video, RtspServer_0.0.0.2
Duration: N/A, start: 0.100000, bitrate: N/A
Stream #0:0: Video: h264 (Baseline), yuv420p(progressive), 320x192, 10 fps, 10 tbr, 90k tbn, 180k tbc
FORMAT pack size 22
Extradata
\00\00\00\01\67\42\00\1f\95\a8\14\01\6e\40\00\00\00\01\68\ce\3c\80\00
---------------------------------------------------
INPUT vc.ril.video_decode:in:0
type: 3, fourcc: H264
bitrate: 0, framed: 0
extra data: 22, 0x1824fd8
width: 320, height: 192, (0,0,320,192)
---------------------------------------------------
OUTPUT vc.ril.video_decode:out:0
type: 3, fourcc: I420
bitrate: 0, framed: 0
extra data: 0, (nil)
width: 320, height: 192, (0,0,320,192)
Press Enter to Continue
Press Enter again to stop
start decoding
NAL TYPE --------------------> 7
\00\00\00\01\67\42\00\1e\f4\0a\0c\c8\00\00\00\01\68\ce\3c\80\00\00\00\01\65\88\84\05\fc\71\c6\3f\62\85\00\02\70\54\b3\d5\01\f0\3d\46\6c\0b\aa\6f\23\7e\57\64\b9\0f\00\0b\09\fd\b5\c8\3a\80\ca\83\88\26\d6\53\36\1f\e0\31\5a\60\13\e4\3d\8b\ca\53\6f\3f\7f\72\37\90\ed\85\c4\5a\43\b1\5e\f3\93\33\62\25\63\b3\97\ff\ff\40\93\9c\5b\a1\0c\01\d0\05\9f\4a\16\e7\41\77\fc\1e\d4\b3\fa\49\ae\00\27\2f\e2\70\b3\09\cf\bf\c9\cb\e4\3d\a9\68\04\52\19\25\a9\03\59\b3\2c\81\0b\6f\70\86\62\8c\87\74\0f\3b\d7\bb\5f\65\38\7c\e4\c7\f9\1b\b1\d8\a5\18\78\c9\9e\31\8c\4e\43\22\8d\ec\11\cb\33\e8\14\8f\c0\4a\c5\2d\67\ee\d6\a0\e2\1b\e4\c2\5c\3f\d6\e7\f8\cc\12\a7\99\c0\0a\07\bf\cf\e4\1d\40\71\61\a2\3f\ea\2b\31\bb\f0\16\7a\24\c2\f7\0f\6f\67\05\bc\22\20\2d\21\ff\ff\b3\f7\cc\b4\3c\85\28\d4\9b\7b\fc\59\b2\1b\47\2b\f3\73\fe\f8\9f\77\f5\02\c4\63\86\10\90\8d\fa\ae\2d\08\85\30\1b\be\66\1c\67\20\0f\9a\ad\83\2c\b9\91\80\8a\44\32\45\0e\2a\30\fd\2d\97\cc\ce\cc\87\74\0b\3b\de\51\bb\5b\97\69\30\32\03\ed\bf\d4\f3\10\58\89\46\..............//This is quite long due to IDR.
vc.ril.video_decode:in:0(H264) sending packet >>>>> 3604 bytes
CONTROL callback called
ERROR: 7
INPUT callback called
Frame number 1
NAL TYPE --------------------> 1
\00\00\00\01\41\9a\24\0d\cf\c6\0a\81\db\2c\e0\0a\f2\4c\37\21\69\a2\e9\86\eb\3c\d9\e3\fe\7f\be\02\d0\d3\ae\6c\66\3f\41\7f\ff\45\73\34\47\0a\76\76\98\bc\3f\8c\98\e6\1e\49\cd\00\e3\c5\ff\50\00\61\1e\91\82\5f\8e\64\6c\92\f9\f9\e8\fe\0b\c4\42\ae\05\dc\74\0b\b0
vc.ril.video_decode:in:0(H264) sending packet >>>>> 85 bytes
Frame number 2
NAL TYPE --------------------> 1
\00\00\00\01\41\9a\48\09\d7\28\a1\e4\df\9b\89\b0\70\ca\59\de\37\01\e0\31\26\71\d1\18\5e
vc.ril.video_decode:in:0(H264) sending packet >>>>> 29 bytes
mmal: mmal_port_send_buffer: vc.ril.video_decode:in:0(H264): send failed: ENOMEM
failed to send buffer to input port
Frame number 3
NAL TYPE --------------------> 1
\00\00\00\01\41\9a\6c\17\3f\16\28\7d\0d\48\1c\0f\99\e9\93\a0\7a\5e\27\96\05\3f\87\e0\b8\78\08\7e\ca\5c\e1\6e\55\29\8d\27\79\ab\0a\51\60\8f\95\3b\e3\20
vc.ril.video_decode:in:0(H264) sending packet >>>>> 50 bytes
mmal: mmal_port_send_buffer: vc.ril.video_decode:in:0(H264): send failed: ENOMEM
failed to send buffer to input port
Frame number 4
NAL TYPE --------------------> 1
\00\00\00\01\41\9a\90\3d\70\80\a3\5c\91\7c\8b\b3\e6\1f\21\bd\77\5d\7c\dd\43\b3\fd\f8\8a\ad\57\22\fe\33\29\18\4a\c0\dc\15\09\48\ad\0c\73\e1\86\2d\43\b4\30\1d\44\40\a1\75\c6\61\bc\b9\9f\19\09\58\aa\ec\e2\c0\fb\6f\1d\f3\4d\2a\cf\e8\6d\7d\4c\5e\55\3b
CONTROL callback called
ERROR: 7
Thanks,
Chris
