I'm modifying this file slightly: https://gist.github.com/yohhoy/f0444d3fc47f2bb2d0e2
This code decodes a video and makes opencv Mats out of the frame pixels as it goes.
In particular I only want to grab frames that have specific macroblock-related data. I'm attempting to get that data like this:
total_qp = get_total_qp(decframe->qscale_table, mb_width, mb_height, mb_stride);
However, whenever I try to access the data by iterating over that array, I get a segmentation fault:
static float get_total_qp(int8_t *qscale_table, int mb_width, int mb_height, int mb_stride)
{
int mb_count = mb_height * mb_width;
int y, x;
float qp_total = 0.0f;
for (y = 0; y < mb_height; y++) {
for (x = 0; x < mb_width; x++) {
qp_total += qscale_table[x + y * mb_stride]; <-- SEGFAULT here
}
}
return qp_total;
}
I've also tried sending in:
frame->qscale_table
and I've tried populating it, but this own't compile because it can't find that function:
int8_t *qscale_table = av_frame_get_qp_table(decframe->qscale_table, &mb_stride, &qscale_type);
So my question is this:
Given an AVFrame* how do I ensure that the qscale_table is populated and access it?
It turns out that the qpscale_table doesn't get exported onto the decoded frame after the decoding happens in h264dec.c.
In order to retrieve the values I had to modify the finalize_frame method in h264dec to export the qscale_table onto the frame, like so:
static int h264_export_qp_table(H264Context *h, AVFrame *f, H264Picture *p, int qp_type)
{
AVBufferRef *ref = av_buffer_ref(p->qscale_table_buf);
int offset = 2*h->mb_stride + 1;
if(!ref)
return AVERROR(ENOMEM);
av_assert0(ref->size >= offset + h->mb_stride * ((f->height+15)/16));
ref->size -= offset;
ref->data += offset;
return av_frame_set_qp_table(f, ref, h->mb_stride, f->qscale_type);
}
and add in the call into finalize_frame:
...
if (CONFIG_MPEGVIDEO) {
ff_print_debug_info2(h->avctx, dst, NULL,
out->mb_type,
out->qscale_table,
out->motion_val,
NULL,
h->mb_width, h->mb_height, h->mb_stride, 1);
// NT: make the qscale_table accessible!
h264_export_qp_table(h, dst, out, FF_QSCALE_TYPE_H264);
}
...
And then recompile FFmpeg using these instructions: https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu
I'm working on making a matrix text rain effect in Processing 3.3 as a simple starter project for learning the processing library and Java. My code so far:
class Symbol {
int x, y;
int switchInterval = round(random(2, 50));
float speed;
char value;
Symbol(int x, int y, float speed) {
this.x = x;
this.y = y;
this.speed = speed;
}
//Sets to random symbol based on the Katakana Unicode block
void setToRandomSymbol() {
if(frameCount % switchInterval == 0) {
value = char((int) random(0x30A0, 0x3100));
}
}
//rains the characters down the screen and loops them to the top when they
// reach the bottom of the screen
void rain() {
if(y <= height) {
y += speed;
}else {
y = 0;
}
}
}
Symbol symbol;
class Stream {
int totalSymbols = round(random(5, 30));
Symbol[] symbols = new Symbol[500];
float speed = random(5, 20);
//generates the symbols and adds them to the array, each symbol one symbol
//height above the one previous
void generateSymbols() {
int y = 0;
int x = width / 2;
for (int i = 0; i <= totalSymbols; i++) {
symbols[i] = new Symbol(x, y, speed);
symbols[i].setToRandomSymbol();
y -= symbolSize;
}
}
void render() {
for(Symbol s : symbols) {
fill(0, 255, 70);
s.setToRandomSymbol();
text(s.value, s.x, s.y);
s.rain();
}
}
}
Ok, so that was a lot of code, Let me explain my dilemma. The issue I'm having is that when I run the code I get a NullpointerException at the s.setToRandomSymbol(); method call in the for each loop in the render function. The weird part about this NullPointerException error and the part I'm not understanding is that it's being thrown on a method that doesn't take in any arguments that could be coming back empty, and the method itself is void, so it shouldn't be returning anything, right? Why is this returning Null and what did I do wrong to have it return this way?
First you come up with a random number betwen 5 and 30:
int totalSymbols = round(random(5, 30));
Then you create an array that holds 500 instances of your Symbol class:
Symbol[] symbols = new Symbol[500];
Note that this array holds 500 null values at this point.
Then you add a maximum of 30 instances of Symbol to your array:
for (int i = 0; i <= totalSymbols; i++) {
symbols[i] = new Symbol(x, y, speed);
Note that this array now holds at least 470 null values at this point.
Then you iterate over all 500 indexes:
for(Symbol s : symbols) {
s.setToRandomSymbol();
But remember that at least 470 of these indexes are null, which is why you're getting a NullPointerException.
Some basic debugging would have told you all of this. I would have started by adding a basic println() statement just before you get the error:
for(Symbol s : symbols) {
println("s: " + s);
s.setToRandomSymbol();
This would have showed you that you're iterating over null values.
Anyway, to fix your problem you need to stop iterating over your entire array, or you need to stop making room for indexes you never use.
In the future, please try to narrow your problem down to a MCVE before posting. Note that this much smaller example program shows your error:
String[] array = new String[10];
array[0] = "test";
for(String s : array){
println(s.length());
}
ok I've come across a weirdness, maybe someone can explain it.
Source code is (c++ 11) :
#include <stdio.h>
struct xyz_ {
float xyz[3];
float &x = xyz[0];
float &y = xyz[1];
float &z = xyz[2];
};
int main(int argc, char *argv[])
{
xyz_ xyz;
xyz.x = 0;
xyz.y = 1;
xyz.z = 2;
xyz.xyz[1] = 1;
printf("as array %f %f %f\n",xyz.xyz[0],xyz.xyz[1],xyz.xyz[2]);
printf("as elements %f %f %f\n",xyz.x,xyz.y,xyz.z);
int sizexyz = sizeof(xyz);
int sizefloat = sizeof(float);
printf("float is %d big, but xyz is %d big\n",sizefloat,sizexyz);
return 0;
}
output is:
as array 0.000000 1.000000 2.000000
as elements 0.000000 1.000000 2.000000
float is 4 big, but xyz is 24 big
So the structure works as I would expect, but the size is twice as large as it should be. Using chars instead of float in the structure gives a segfault when run.
I wanted to use struct xyz_ as either an array of floats or individual float elements.
It is unspecified whether references require storage. In this case your output suggests that your compiler has decided to use storage to implement the references x, y and z.
Suppose you add another constructor:
struct xyz_ {
float xyz[3];
float &x = xyz[0];
float &y = xyz[1];
float &z = xyz[2];
xyz_()
{
}
xyz_(float& a, float& b, float& c)
: x(a), y(b), z(c)
{
}
};
It should be clear that now the three x, y and z members may be bound to the array elements or may be bound to something else.
Looks like what you are looking for is
union P3d {
float xyz[3];
struct {
float x, y, z;
};
};
Unfortunately for some strange reasons (apparently mostly political) this is not supported in the standard (despite compilers do actually support it).
How about this:
struct xyz_
{
float xyz[3];
float &x() {return xyz[0];}
float &y() {return xyz[1];}
float &z() {return xyz[2];}
};
Not as beautiful or elegant, but might reduce the size a bit, though I think the this pointer might occupy additional space, not sure...
Of course you would have to use x(), y() and z().
What would be the size of xyz_ if it's declared like this?
struct xyz_ {
float xyz[3];
float *x = &xyz[0];
float *y = &xyz[1];
float *z = &xyz[2];
};
The reference also needs it's own space to store the information where it is pointing at.
In C you could do the following, but it's not legal in C++11.
union xyz_ {
float xyz[3];
struct { float x, y, z; };
};
I have a code like this:
float[] x = {5,11,17,23,26,23,18,12,7,4,5,6,7,6,3,2,5,5,4,3,3,5,10,18,26,32,26,18,10,5,2,10,12,14,15,9,8,14,13,9,7,5,3,8,17,33,49,32,16,7,3,1,13,16,23,31,26,25,30,22,14,9,7,0,1,9,38,101,38,9,0,1,0,12,17,32,60,89,88,59,30,15,8,6,6,14,19,10,279,10,19,14,8,3,6,10,26,89,360,359,88,25,9,4,2,10,30,82,259,1000,260,82,32,13,5,5,9,26,89,358,359,89,26,9,4,3,6,13,19,9,280,9,20,14,8,3,11,17,31,60,89,89,60,31,16,9,6,0,1,9,38,102,38,9,0,1,0,12,16,23,30,25,25,31,22,14,10,7,3,8,17,33,50,33,17,8,3,1,9,11,13,14,8,9,15,13,10,7,6,5,10,18,27,33,27,18,11,6,3,5,6,6,6,2,3,6,6,5,4,1,5,11,18,24,27,24,18,12,7,3};
void setup(){
size(620,620);
float k=1;
float q=0;
for (float j=0;j<height;j=j+30){
if(k%2!=0){
for(float i=30;i<width;i=i+60){
fill(kolor(x[q]));
rect(i,j,20,20);
q=q+1;
}
k++;
} else {
for(float i=0;i<width;i=i+60){
fill(kolor(x[q]));
rect(i,j,20,20);
q=q+1;
}
k++;
}
}
}
float kolor(float input){
return map(input,0,1000,0,255);
}
When I try to compile, I get "cannot convert float to int" error, connected with lines fill(kolor(x[q]));.
I tried changing this to fill((int)kolor(x[q]));.
Do you have any idea how to fix this?
The problem with line fill((int)kolor(x[q]) is that x is an array, and you can only access array members by using ints, while you access it using q which is a float.
Try changing float q = 0; to int q = 0;
By the way, it looks like java code, is it java?
Why are you using floats in the first place? You probably should be using ints, especially with the % in there.
Here is the signature of the fill() command, for those interested.